Revision: 20806 http://sourceforge.net/p/jmol/code/20806 Author: hansonr Date: 2015-10-04 04:16:41 +0000 (Sun, 04 Oct 2015) Log Message: ----------- Jmol.___JmolVersion="14.3.16_2015.10.03"
new feature: if, for, and while can all operate using no braces for single-line bodies -- similar to JavaScript and Java -- examples: for(var i = 0; i < 10; i++) for(var j = 0; j < 10; j++) print i*j if (i == 1) print i else print 0 bug fix: translucent echo backgrounds not saved in state properly Modified Paths: -------------- trunk/Jmol/src/org/jmol/script/ScriptCompiler.java trunk/Jmol/src/org/jmol/script/ScriptEval.java trunk/Jmol/src/org/jmol/script/ScriptFlowContext.java trunk/Jmol/src/org/jmol/script/T.java trunk/Jmol/src/org/jmol/viewer/Jmol.properties trunk/Jmol/src/org/jmol/viewer/StateCreator.java trunk/Jmol/src/org/openscience/jmol/app/JmolApp.java Modified: trunk/Jmol/src/org/jmol/script/ScriptCompiler.java =================================================================== --- trunk/Jmol/src/org/jmol/script/ScriptCompiler.java 2015-10-02 02:19:13 UTC (rev 20805) +++ trunk/Jmol/src/org/jmol/script/ScriptCompiler.java 2015-10-04 04:16:41 UTC (rev 20806) @@ -250,7 +250,7 @@ private void addTokenToPrefix(T token) { if (logMessages) - Logger.info("addTokenToPrefix" + token); + Logger.info("addTokenToPrefix" + lineCurrent + " " + iCommand + " " + token); ltoken.addLast(token); if (token.tok != T.nada) lastToken = token; @@ -365,6 +365,20 @@ checkImpliedScriptCmd = false; if (ichToken < cchScript) continue; + if (flowContext != null) { + ichCurrentCommand = cchScript; + while (flowContext != null) { + fixFlowAddLine(flowContext); + if (flowContext.checkForceEndIf(0)) { + forceFlowEnd(flowContext.token); + ichCurrentCommand = cchScript; + processTokenList(iLine, isFull); + } else { + flowContext = flowContext.parent; + } + } + lltoken.addLast(new T[]{T.o(T.nada, "// end of script")}); + } setAaTokenCompiled(); return (flowContext == null || errorStr(ERROR_missingEnd, T.nameOf(flowContext.token.tok))); @@ -385,7 +399,7 @@ case ERROR: return false; } - switch (parseCommandParameter()) { + switch (parseCommandParameter(iLine, isFull)) { case CONTINUE: continue; case ERROR: @@ -446,11 +460,17 @@ return true; switch (tokCommand) { case T.forcmd: + case T.whilecmd: + case T.ifcmd: + case T.elsecmd: + case T.elseif: + // end of a line, after (...), no { flowContext.addLine = 1; + flowContext.forceEndIf = true; return false; case T.set: - if (isNewSet) - break; + if (nTokens > 1 && ltoken.get(1).tok == T.echo) + return false; //$FALL-THROUGH$ case T.print: case T.log: @@ -632,8 +652,9 @@ } private int processTokenList(short iLine, boolean doCompile) { - if (nTokens > 0 || comment != null) { - if (nTokens == 0) { + int n = ltoken.size(); + if (n > 0 || comment != null) { + if (n == 0) { // just a comment ichCurrentCommand = ichToken; if (comment != null) { @@ -646,7 +667,7 @@ if (wasImpliedScript()) return CONTINUE; if (isNewSet - && nTokens > 2 + && n > 2 && tokAt(2) == T.per && (tokAt(3) == T.sort || tokAt(3) == T.reverse || tokAt(3) == T.push || tokAt(3) == T.pop)) { // check for x.sort or x.reverse or a.push(xxx) @@ -664,7 +685,7 @@ if (thisFunction != null && thisFunction.cmdpt0 < 0) { thisFunction.cmdpt0 = iCommand; } - if (nTokens == 1 && braceCount == 1) { + if (n == 1 && braceCount == 1) { // ...{... if (lastFlowCommand == null) { parenCount = setBraceCount = braceCount = 0; @@ -681,11 +702,12 @@ if (lastFlowCommand.tok != T.process && (tokAt(0) == T.leftbrace)) ltoken.remove(0); lastFlowCommand = null; + lastFlowContext = flowContext; } } if (bracketCount > 0 || setBraceCount > 0 || parenCount > 0 || braceCount == 1 && !checkFlowStartBrace(true)) { - error(nTokens == 1 ? ERROR_commandExpected + error(n == 1 ? ERROR_commandExpected : ERROR_endOfCommandUnexpected); return ERROR; } @@ -714,7 +736,7 @@ if (doCompile && !compileCommand()) return ERROR; if (logMessages) { - Logger.debug("-------------------------------------"); + Logger.info("-------------------------------------"); } boolean doEval = true; switch (tokCommand) { @@ -760,13 +782,23 @@ } if (endOfLine) { - if (flowContext != null && flowContext.checkForceEndIf()) { - if (!isComment) + if (flowContext != null && flowContext.checkForceEndIf(-1)) { + if (isComment) { + if (flowContext.addLine > 0) { + flowContext.addLine++; + flowContext.forceEndIf = true; + } + } else if (n > 0) { forceFlowEnd(flowContext.token); + if (lastFlowContext.addLine > 0) { + lastFlowContext.forceEndIf = true; + } + } isEndOfCommand = true; cchToken = 0; ichCurrentCommand = ichToken; - lineCurrent--; + if (n > 0) + lineCurrent--; return CONTINUE; } isComment = false; @@ -1391,7 +1423,7 @@ //$FALL-THROUGH$ case T.endifcmd: if (flowContext != null) - flowContext.forceEndIf = false; + flowContext.forceEndIf = false; //$FALL-THROUGH$ case T.elsecmd: if (nTokens > 0) { @@ -1456,14 +1488,21 @@ } break; case T.leftbrace: - braceCount++; - if (braceCount == 1 && parenCount == 0 && checkFlowStartBrace(false)) { + if (++braceCount == 1 && parenCount == 0 && checkFlowStartBrace(false)) { + // specifically for else { but not elseIf ( ) { isEndOfCommand = true; - if (flowContext != null) - flowContext.forceEndIf = false; + ScriptFlowContext f = (flowContext != null && flowContext.addLine == 0 + || lastFlowContext == null ? flowContext : lastFlowContext); + if (f != null) { + f.addLine = 0; + f.forceEndIf = false; + lastToken = T.tokenLeftBrace; + lastFlowContext = f; + } return CONTINUE; } - //$FALL-THROUGH$ + parenCount++; + break; case T.leftparen: parenCount++; // the select() function uses dual semicolon notation @@ -1495,8 +1534,7 @@ braceCount--; //$FALL-THROUGH$ case T.rightparen: - parenCount--; - if (parenCount < 0) + if (--parenCount < 0) return ERROR(ERROR_tokenUnexpected, ident); // we need to remove the semiskip if parentheses or braces have been // closed. 11.5.46 @@ -1552,7 +1590,7 @@ return true; } - private int parseCommandParameter() { + private int parseCommandParameter(short iLine, boolean isFull) { // PART II: // // checking tokens based on the current command @@ -1601,8 +1639,23 @@ tokCommand = T.nada; return CONTINUE; } - if (theTok != T.leftbrace) + + if (theTok != T.leftbrace) { + if (flowContext != null) { + fixFlowAddLine(flowContext); + while (flowContext != null) { + if (flowContext.checkForceEndIf(0)) { + forceFlowEnd(flowContext.token); + processTokenList(iLine, isFull); + setCommand(theToken); + theTok = theToken.tok; + } else { + break; + } + } + } lastFlowCommand = null; + } if (theTok == T.opAnd) { //& introduces a resume context @@ -1743,48 +1796,39 @@ return CONTINUE; } break; - case T.switchcmd: - case T.whilecmd: - if (nTokens > 2 && braceCount == 0 && parenCount == 0) { - isEndOfCommand = true; - ichEnd = ichToken + 1; - flowContext.setLine(); - } - break; - case T.elseif: - case T.ifcmd: - if (nTokens > 2 && braceCount == 0 && parenCount == 0) { - // so { or : end up new commands - isEndOfCommand = true; - ichEnd = ichToken + 1; - flowContext.setLine(); - } - break; - case T.process: - isEndOfCommand = true; - ichEnd = ichToken + 1; - flowContext.setLine(); - break; case T.forcmd: if (nTokens == 1) { if (theTok != T.leftparen) return ERROR(ERROR_unrecognizedToken, ident); forPoint3 = nSemiSkip = 0; nSemiSkip += 2; - } else if (nTokens == 3 && tokAt(2) == T.var) { + break; + } + if (nTokens == 3 && tokAt(2) == T.var) { newContextVariable(ident); - } else if ((nTokens == 3 || nTokens == 4) && theTok == T.in) { + break; + } + if ((nTokens == 3 || nTokens == 4) && theTok == T.in) { // for ( var x IN // for ( x IN nSemiSkip -= 2; forPoint3 = 2; addTokenToPrefix(theToken); theToken = T.tokenLeftParen; - } else if (braceCount == 0 && parenCount == 0) { - isEndOfCommand = true; - ichEnd = ichToken + 1; - flowContext.setLine(); - } + break; + } + //$FALL-THROUGH$ + case T.switchcmd: + case T.whilecmd: + case T.elseif: + case T.ifcmd: + if (nTokens <= 2 ||braceCount != 0 || parenCount != 0) + break; + //$FALL-THROUGH$ + case T.process: + isEndOfCommand = true; + ichEnd = ichToken + 1; + flowContext.setLine(); break; case T.var: if (nTokens == 1) { @@ -1945,7 +1989,8 @@ } private boolean checkFlowStartBrace(boolean atEnd) { - if ((!T.tokAttr(tokCommand, T.flowCommand) || tokCommand == T.breakcmd || tokCommand == T.continuecmd)) + int tok = tokCommand; + if ((!T.tokAttr(tok, T.flowCommand) || tok == T.breakcmd || tok == T.continuecmd)) return false; if (atEnd) { if (tokenCommand.tok != T.casecmd && tokenCommand.tok != T.defaultcmd) { @@ -1960,6 +2005,7 @@ Lst<T> vPush = new Lst<T>(); int pushCount; + private ScriptFlowContext lastFlowContext; private int checkFlowEndBrace() { @@ -1994,9 +2040,10 @@ } return forceFlowEnd(token); } - private int forceFlowEnd(T token) { + // need to be able to UNDO this. T t0 = tokenCommand; + lastFlowContext = flowContext; setCommand(T.o(T.end, "end")); if (!checkFlowCommand("end")) return T.nada; @@ -2059,6 +2106,22 @@ case T.switchcmd: case T.whilecmd: break; + case T.elseif: + case T.elsecmd: + if (lastFlowContext != null && lastFlowContext.forceEndIf + && lastFlowContext.addLine > 0) { + flowContext = lastFlowContext; + flowContext.forceEndIf = true; + if (isFlowIfContextOK(flowContext, tokCommand) + && lltoken.get(iCommand - 1)[0].tok == T.end) + lltoken.remove(pt = --iCommand); + } + if (flowContext != null && !isFlowIfContextOK(flowContext, tokCommand)) + flowContext = flowContext.parent; + if (!isFlowIfContextOK(flowContext, tokCommand)) + return errorStr(ERROR_badContext, ident); + flowContext.token.intValue = flowContext.setPt0(pt, false); + break; case T.endifcmd: isEnd = true; if (flowContext == null || flowContext.token.tok != T.ifcmd @@ -2067,12 +2130,6 @@ && flowContext.token.tok != T.elseif) return errorStr(ERROR_badContext, ident); break; - case T.elsecmd: - if (flowContext == null || flowContext.token.tok != T.ifcmd - && flowContext.token.tok != T.elseif) - return errorStr(ERROR_badContext, ident); - flowContext.token.intValue = flowContext.setPt0(pt, false); - break; case T.breakcmd: case T.continuecmd: isNew = false; @@ -2081,38 +2138,27 @@ if (tokCommand == T.continuecmd) while (f != null && f.token.tok != T.forcmd && f.token.tok != T.whilecmd) - f = f.getParent(); + f = f.parent; if (f == null) return errorStr(ERROR_badContext, ident); setCommand(T.tv(tokCommand, f.pt0, ident)); //copy break; + case T.casecmd: case T.defaultcmd: - if (flowContext == null || flowContext.token.tok != T.switchcmd - && flowContext.token.tok != T.casecmd && flowContext.ptDefault > 0) - return errorStr(ERROR_badContext, ident); - flowContext.token.intValue = flowContext.setPt0(pt, true); - break; - case T.casecmd: - if (flowContext == null || flowContext.token.tok != T.switchcmd + if (flowContext == null + || flowContext.token.tok != T.switchcmd && flowContext.token.tok != T.casecmd - && flowContext.token.tok != T.defaultcmd) + && (tokCommand == T.defaultcmd ? flowContext.ptDefault > 0 + : flowContext.token.tok != T.defaultcmd)) return errorStr(ERROR_badContext, ident); - flowContext.token.intValue = flowContext.setPt0(pt, false); + flowContext.token.intValue = flowContext.setPt0(pt, + tokCommand == T.defaultcmd); break; - case T.elseif: - if (flowContext == null || flowContext.token.tok != T.ifcmd - && flowContext.token.tok != T.elseif - && flowContext.token.tok != T.elsecmd) - return errorStr(ERROR_badContext, "elseif"); - flowContext.token.intValue = flowContext.setPt0(pt, false); - break; } if (isEnd) { flowContext.token.intValue = (tokCommand == T.catchcmd ? -pt : pt); if (tokCommand == T.endifcmd) - flowContext = flowContext.getParent(); - // if (tokCommand == T.trycmd) { - // } + flowContext = flowContext.parent; } else if (isNew) { ContextToken ct = ContextToken.newCmd(tokCommand, tokenCommand.value); if (tokCommand == T.switchcmd) @@ -2128,13 +2174,12 @@ pushCount++; vPush.addLast(ct); break; - case T.elsecmd: - case T.elseif: - flowContext.token = ct; - break; case T.casecmd: case T.defaultcmd: ct.contextVariables = flowContext.token.contextVariables; + //$FALL-THROUGH$ + case T.elsecmd: + case T.elseif: flowContext.token = ct; break; case T.process: @@ -2154,6 +2199,12 @@ return true; } + private boolean isFlowIfContextOK(ScriptFlowContext f, int tokCommand) { + return (f != null && (f.token.tok == T.ifcmd + || f.token.tok == T.elseif + || f.token.tok == T.elsecmd && tokCommand != T.elsecmd)); + } + private boolean checkFlowEnd(int tok, String ident, int pt1) { if (flowContext == null || flowContext.token.tok != tok) { boolean isOK = true; @@ -2197,10 +2248,21 @@ default: return errorStr(ERROR_unrecognizedToken, "end " + ident); } - flowContext = flowContext.getParent(); + flowContext = flowContext.parent; + fixFlowAddLine(flowContext); return true; } + private void fixFlowAddLine(ScriptFlowContext flowContext) { + while (flowContext != null) { + if (flowContext.addLine > 0) { + flowContext.addLine = lineCurrent - flowContext.ptLine; + flowContext.forceEndIf = true; + } + flowContext = flowContext.parent; + } + } + private boolean getData(String key) { addTokenToPrefix(T.o(T.string, key)); ichToken += key.length() + 2; Modified: trunk/Jmol/src/org/jmol/script/ScriptEval.java =================================================================== --- trunk/Jmol/src/org/jmol/script/ScriptEval.java 2015-10-02 02:19:13 UTC (rev 20805) +++ trunk/Jmol/src/org/jmol/script/ScriptEval.java 2015-10-04 04:16:41 UTC (rev 20806) @@ -2144,7 +2144,7 @@ } if (!chk && !checkContinue()) break; - if (lineNumbers[pc] > lineEnd) + if (pc >= lineNumbers.length || lineNumbers[pc] > lineEnd) break; if (debugHigh) { long timeBegin = 0; @@ -3449,8 +3449,8 @@ isOK = (j >= 0); } } else { - // for (i = 1; i < 3; i = i + 1); + // for (i = 1; i < 3; i = i + 1); // for (var i = 1; i < 3; i = i + 1); // for (;;;); // for (var x in {...}) { xxxxx } @@ -3577,15 +3577,16 @@ forVars[0] = forVar; forVars[1] = forVal; } else { - if (T.tokAttr(tokAt(j), T.misc) - || (forVal = getContextVariableAsVariable(key, false)) != null) { + int vtok = tokAt(j); + if (vtok != T.semicolon && (T.tokAttr(vtok, T.misc) + || (forVal = getContextVariableAsVariable(key, false)) != null)) { if (!isMinusMinus && getToken(++j).tok != T.opEQ) invArg(); if (isMinusMinus) j -= 2; setVariable(++j, slen - 1, key, false); } - isOK = parameterExpressionBoolean(pts[0] + 1, pts[1]); + isOK = (pts[0] + 1 == pts[1] || parameterExpressionBoolean(pts[0] + 1, pts[1])); } } if (isOK && tok == T.in && j >= 0) { Modified: trunk/Jmol/src/org/jmol/script/ScriptFlowContext.java =================================================================== --- trunk/Jmol/src/org/jmol/script/ScriptFlowContext.java 2015-10-02 02:19:13 UTC (rev 20805) +++ trunk/Jmol/src/org/jmol/script/ScriptFlowContext.java 2015-10-04 04:16:41 UTC (rev 20806) @@ -142,14 +142,14 @@ int ptDefault; ScriptFunction function; SV var; - private ScriptFlowContext parent; + ScriptFlowContext parent; int lineStart; int commandStart; int ptLine; int ptCommand; boolean forceEndIf = true; String ident; - public int addLine; + int addLine; ScriptFlowContext(ScriptCompiler compiler, ContextToken token, int pt0, ScriptFlowContext parent) { this.compiler = compiler; @@ -165,15 +165,16 @@ ScriptFlowContext getBreakableContext(int nLevelsUp) { ScriptFlowContext f = this; while (f != null && (!ScriptCompiler.isBreakableContext(f.token.tok) || nLevelsUp-- > 0)) - f = f.getParent(); + f = f.parent; return f; } - boolean checkForceEndIf() { + boolean checkForceEndIf(int offset) { + if (ptCommand == compiler.iCommand && addLine > 0) + addLine++; boolean test = forceEndIf - && ptCommand < this.compiler.iCommand - && ptLine + addLine == this.compiler.lineCurrent; - //System.out.println("checking" + pt + " " + test + " " + ident + " " + forceEndIf + " " + ptCommand + " " + iCommand + "/" + ptLine + " " + lineCurrent); + && ptCommand < compiler.iCommand + && ptLine + (addLine == 0 ? 0 : addLine + offset) == compiler.lineCurrent; if (test) // only once! forceEndIf = false; return test; @@ -188,8 +189,8 @@ } void setLine() { - ptLine = this.compiler.lineCurrent; - ptCommand = this.compiler.iCommand + 1; + ptLine = compiler.lineCurrent; + ptCommand = compiler.iCommand + 1; } @Override @@ -199,11 +200,6 @@ + " command " + commandStart; } - ScriptFlowContext getParent() { - //System.out.println("FlowContext end " + path() + " on line/command " + lineCurrent + " " + iCommand); - return parent; - } - String path() { String s = ""; ScriptFlowContext f = this; Modified: trunk/Jmol/src/org/jmol/script/T.java =================================================================== --- trunk/Jmol/src/org/jmol/script/T.java 2015-10-02 02:19:13 UTC (rev 20805) +++ trunk/Jmol/src/org/jmol/script/T.java 2015-10-04 04:16:41 UTC (rev 20806) @@ -1387,6 +1387,7 @@ public final static T tokenArraySquare = o(array, "["); // special operator stack flag public final static T tokenArrayOpen = o(leftsquare, "["); // used also as special operand stack flag public final static T tokenArrayClose = o(rightsquare, "]"); + public final static T tokenLeftBrace = o(leftbrace, "{"); public final static T tokenExpressionBegin = o(expressionBegin, "expressionBegin"); public final static T tokenExpressionEnd = o(expressionEnd, "expressionEnd"); Modified: trunk/Jmol/src/org/jmol/viewer/Jmol.properties =================================================================== --- trunk/Jmol/src/org/jmol/viewer/Jmol.properties 2015-10-02 02:19:13 UTC (rev 20805) +++ trunk/Jmol/src/org/jmol/viewer/Jmol.properties 2015-10-04 04:16:41 UTC (rev 20806) @@ -61,10 +61,34 @@ TODO: consider if models with no atoms will cause issues in relation to model.firstAtomIndex -Jmol.___JmolVersion="14.3.16_2015.10.01" +Jmol.___JmolVersion="14.3.16_2015.10.03" + +new feature: if, for, and while can all operate using no braces for single-line bodies + -- similar to JavaScript and Java + -- examples: + + for(var i = 0; i < 10; i++) + for(var j = 0; j < 10; j++) + print i*j + + if (i == 1) + print i + else + print 0 + +bug fix: translucent echo backgrounds not saved in state properly + + +JmolVersion="14.3.16_2015.10.01" + +bug fix: for (; i < 10; i++) not working +bug fix: for (;;i++) not working +bug fix: for (;;) not working + +JmolVersion="14.3.16_2015.10.01" bug fix: hydrogens added to backbone should be part of "backbone" definition - -- no-hydrogen definition is _bb, but that is + -- no-hydrogen definition is _bb new feature: calculate hydrogens TRUE -- calculates hydrogens and multiple bonding Modified: trunk/Jmol/src/org/jmol/viewer/StateCreator.java =================================================================== --- trunk/Jmol/src/org/jmol/viewer/StateCreator.java 2015-10-02 02:19:13 UTC (rev 20805) +++ trunk/Jmol/src/org/jmol/viewer/StateCreator.java 2015-10-04 04:16:41 UTC (rev 20806) @@ -1357,10 +1357,10 @@ s.append(C.getColixTranslucencyLabel(t.colix)); s.append(" ").append(C.getHexCode(t.colix)); if (t.bgcolix != 0) { - s.append("; color echo background"); + s.append("; color echo background "); if (C.isColixTranslucent(t.bgcolix)) - s.append(C.getColixTranslucencyLabel(t.bgcolix)); - s.append(" ").append(C.getHexCode(t.bgcolix)); + s.append(C.getColixTranslucencyLabel(t.bgcolix)).append(" "); + s.append(C.getHexCode(t.bgcolix)); } s.append(";\n"); return s.toString(); Modified: trunk/Jmol/src/org/openscience/jmol/app/JmolApp.java =================================================================== --- trunk/Jmol/src/org/openscience/jmol/app/JmolApp.java 2015-10-02 02:19:13 UTC (rev 20805) +++ trunk/Jmol/src/org/openscience/jmol/app/JmolApp.java 2015-10-04 04:16:41 UTC (rev 20806) @@ -130,9 +130,8 @@ args = line.getArgs(); if (args.length > 0) { - modelFilename = args[0]; + modelFilename = args[0]; } - checkOptions(line, options); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ _______________________________________________ Jmol-commits mailing list Jmol-commits@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jmol-commits