Revision: 20789 http://sourceforge.net/p/jmol/code/20789 Author: hansonr Date: 2015-09-22 12:17:07 +0000 (Tue, 22 Sep 2015) Log Message: ----------- Jmol.___JmolVersion="14.3.16_2015.09.22"
bug fix: x.format("JSON") fails for recursive x -- arrays or associative arrays can be recursive -- detection of recursion now delivers empty array or associative array -- example: $ a = [[1,2],3] $ a..2 = a $ print a.format("JSON") [ [ 1,2 ],[ [ 1,2 ],[ ] ] ] $ a = [b:1] $ a.b = a $ print a.format("JSON") { "b": { "b": { } } } new feature: x = @a -- deep copy for a = array or associative array -- @a for string variable still gets the value of the variable named by variable a -- math environment only, not SELECT new feature: for allows one continuation line, as in JavaScript and Java -- for example: for (i = 1; i <= 3; i++) print i; bug fix: for (key in hash){...} fails upon functional iteration (deepCopy) -- code was reusing the FOR variable when it should have been caching it in the context stack Modified Paths: -------------- trunk/Jmol/src/org/jmol/script/SV.java trunk/Jmol/src/org/jmol/script/ScriptExpr.java trunk/Jmol/src/org/jmol/viewer/Jmol.properties Modified: trunk/Jmol/src/org/jmol/script/SV.java =================================================================== --- trunk/Jmol/src/org/jmol/script/SV.java 2015-09-22 04:53:25 UTC (rev 20788) +++ trunk/Jmol/src/org/jmol/script/SV.java 2015-09-22 12:17:07 UTC (rev 20789) @@ -646,17 +646,18 @@ } private static void sValueArray(SB sb, SV vx, String path, String tabs, - boolean isEscaped, boolean isRaw, boolean addValues, int maxLevels, boolean skipEmpty) { - if (vx == null) - System.out.println("hoho"); + boolean isEscaped, boolean isRaw, + boolean addValues, int maxLevels, + boolean skipEmpty) { switch (vx.tok) { case hash: case context: case varray: String thiskey = ";" + vx.hashCode() + ";"; if (path.indexOf(thiskey) >= 0) { - sb.append(isEscaped ? "{}" : vx.myName == null ? "\0\"<circular reference>\"" - : "<" + vx.myName + ">"); + sb.append(isEscaped ? (vx.tok == varray ? "[ ]" : "{ }") + : (vx.tok == varray ? "" : "\0") + "\"<" + + (vx.myName == null ? "circular reference" : vx.myName) + ">\""); break; } path += thiskey; @@ -670,16 +671,18 @@ if (isEscaped && i > 0) sb.append(","); SV sv = sx.get(i); - sValueArray(sb, sv, path, tabs + " ", isEscaped, tabs.length() == 0 && !isEscaped && isRawType(sv.tok), addValues, maxLevels, skipEmpty); + sValueArray(sb, sv, path, tabs + " ", isEscaped, tabs.length() == 0 + && !isEscaped && isRawType(sv.tok), addValues, maxLevels, + skipEmpty); if (!isEscaped) sb.append("\n"); } if (!isRaw) sb.append(isEscaped ? " ]" : tabs + "]"); - } else if (--maxLevels >= 0){ + } else if (--maxLevels >= 0) { Map<String, SV> ht = (vx.tok == context ? ((ScriptContext) vx.value) .getFullMap() : vx.getMap()); - addKeys(sb, path, ht, tabs, isEscaped, addValues, maxLevels, skipEmpty); + sValueAddKeys(sb, path, ht, tabs, isEscaped, addValues, maxLevels, skipEmpty); } break; default: @@ -691,7 +694,7 @@ } } - private static void addKeys(SB sb, String path, Map<String, SV> ht, String tabs, boolean isEscaped, boolean addValues, int maxLevels, boolean skipEmpty) { + private static void sValueAddKeys(SB sb, String path, Map<String, SV> ht, String tabs, boolean isEscaped, boolean addValues, int maxLevels, boolean skipEmpty) { if (maxLevels < 0) return; Set<String> keyset = ht.keySet(); @@ -703,8 +706,8 @@ for (int i = 0; i < keys.length; i++) { String key = keys[i]; SV val = ht.get(key); - if (skipEmpty && (val.tok == T.varray && val.getList().size() == 0 - || val.tok == T.hash && val.getMap().isEmpty())) + if (skipEmpty && (val.tok == varray && val.getList().size() == 0 + || val.tok == hash && val.getMap().isEmpty())) continue; if (addValues) sb.append(sep).append(PT.esc(key)).append(":"); @@ -741,15 +744,15 @@ private static boolean isRawType(int tok) { switch (tok) { - case T.string: - case T.decimal: - case T.integer: - case T.point3f: - case T.point4f: - case T.bitset: - case T.barray: - case T.on: - case T.off: + case string: + case decimal: + case integer: + case point3f: + case point4f: + case bitset: + case barray: + case on: + case off: return true; } return false; @@ -1185,7 +1188,7 @@ private static String sprintf(String strFormat, SV var, Object[] of, int[] vd, float[] vf, double[] ve, boolean getS, boolean getP, boolean getQ) { - if (var.tok == T.hash) { + if (var.tok == hash) { int pt = strFormat.indexOf("["); if (pt >= 0) { int pt1; @@ -1240,7 +1243,11 @@ pt = getFormatType(args[0].asString()); switch (pt) { case 0: - return args[1].toJSON(); + String name = args[1].myName; + args[1].myName = null; + Object o = args[1].toJSON(); + args[1].myName = name; + return o; case 5: case 12: case 22: @@ -1281,8 +1288,8 @@ sb.append(format[0]); for (int i = 1; i < format.length; i++) { Object ret = sprintf(PT.formatCheck("%" + format[i]), - (args[1].tok == T.hash ? args[1] - : args[1].tok == T.varray ? args[1].getList().get(i - 1) + (args[1].tok == hash ? args[1] + : args[1].tok == varray ? args[1].getList().get(i - 1) : i < args.length ? args[i] : null)); if (AU.isAS(ret)) { String[] list = (String[]) ret; @@ -1595,8 +1602,18 @@ return PT.byteArrayToJSON(((BArray) value).data); case context: return PT.toJSON(null, ((ScriptContext) value).getFullMap()); + case varray: + case hash: + if (myName != null) { + myName = null; + return (tok == hash ? "{ }" : "[ ]"); + } + myName = "x"; + String s = PT.toJSON(null, value); + myName = null; + return s; default: - return PT.toJSON(null, value); + return PT.toJSON(null, value); } } @@ -1634,9 +1651,9 @@ public String[] getKeys(boolean isAll) { switch (tok) { - case T.hash: - case T.context: - case T.varray: + case hash: + case context: + case varray: break; default: return null; @@ -1672,36 +1689,49 @@ } } + /** + * Copies a hash or array deeply; invoked by Jmol script + * + * x = @a + * + * where a.type == "hash" or a.type == "varray" + * + * + * @param v hash or array + * @param isHash + * @return deeply copied variable + */ @SuppressWarnings("unchecked") public static Object deepCopy(Object v, boolean isHash) { if (isHash) { + Map<String, SV> vold = (Map<String, SV>) v; Map<String, SV> vnew = new Hashtable<String, SV>(); - Map<String, SV> vold = (Map<String, SV>) v; - for (Entry<String, SV> e : vold.entrySet()) { - SV vm = e.getValue(); - switch (vm.tok) { - case hash: - case varray: - vm = newV(vm.tok, deepCopy(vm.value, vm.tok == hash)); - break; - } - vnew.put(e.getKey(), vm); - } + for (Entry<String, SV> e : vold.entrySet()) + vnew.put(e.getKey(), deepCopySV(e.getValue())); return vnew; } + Lst<SV> vold2 = (Lst<SV>) v; Lst<SV> vnew2 = new Lst<SV>(); - Lst<SV> vold2 = (Lst<SV>) v; - for (int i = 0, n = vold2.size(); i < n; i++) { - SV vm = vold2.get(i); - switch (vm.tok) { - case hash: - case varray: + for (int i = 0, n = vold2.size(); i < n; i++) + vnew2.addLast(deepCopySV(vold2.get(i))); + return vnew2; + } + + private static SV deepCopySV(SV vm) { + switch (vm.tok) { + case hash: + case varray: + if (vm.myName != null) { + vm.myName = null; + vm = SV.newV(vm.tok, (vm.tok == hash ? new Hashtable<String, SV>() : new Lst<SV>())); + } else { + vm.myName = "recursing"; + SV vm0 = vm; vm = newV(vm.tok, deepCopy(vm.value, vm.tok == hash)); - break; + vm0.myName = null; } - vnew2.addLast(vm); + break; } - return vnew2; + return vm; } - } Modified: trunk/Jmol/src/org/jmol/script/ScriptExpr.java =================================================================== --- trunk/Jmol/src/org/jmol/script/ScriptExpr.java 2015-09-22 04:53:25 UTC (rev 20788) +++ trunk/Jmol/src/org/jmol/script/ScriptExpr.java 2015-09-22 12:17:07 UTC (rev 20789) @@ -2434,6 +2434,8 @@ v = SV.oValue(vt); } else if (!isExpression) { v = vt; + } else if (chk) { + v = null; } else { // select @{x} where x is an array BS bs = SV.getBitSet(vt, true); @@ -2447,6 +2449,8 @@ } } i = iToken; + } else if (chk) { + v = null; } else { if (tokAt(i) == T.integer) { v = vwr.ms.getAtoms(T.atomno, Integer.valueOf(st[i].intValue)); @@ -2460,7 +2464,10 @@ } tok = tokAt(0); forceString |= (T.tokAttr(tok, T.implicitStringCommand) || tok == T.script); // for the file names - if (v instanceof SV) { + if (v == null) { + // + fixed[j] = T.tokenAll; + } else if (v instanceof SV) { // select @{...} fixed[j] = (T) v; } else if (v instanceof Boolean) { @@ -2492,8 +2499,9 @@ // select @x where x is "arg", for example // but not chain=@x -- in that case we need a literal value - fixed[j] = (s.indexOf("|") >= 0 || T.tokAttr(fixed[j - 1].tok, T.comparator) ? T.o( - T.string, s) : T.o(T.bitset, getAtomBitSet(s))); + fixed[j] = (s.indexOf("|") >= 0 + || T.tokAttr(fixed[j - 1].tok, T.comparator) ? T.o(T.string, + s) : T.o(T.bitset, getAtomBitSet(s))); } else { // bit of a hack here.... @@ -2529,17 +2537,18 @@ fixed[j] = SV.newV(T.point4f, v); } else if (v instanceof M34) { fixed[j] = SV.newV(v instanceof M4 ? T.matrix4f : T.matrix3f, v); - } else if (v instanceof Map<?, ?>) { + } else if (v instanceof Map<?, ?> || v instanceof ScriptContext + && (v = ((ScriptContext) v).getFullMap()) != null) { + // do a deep copy -- Jmol 14.3.16 fixed[j] = SV.newV(T.hash, (isExpression ? v : SV.deepCopy(v, true))); - } else if (v instanceof ScriptContext) { - fixed[j] = SV.newV(T.hash, ((ScriptContext) v).getFullMap()); } else if (v instanceof Lst<?>) { - // if v is a list, we check to to see if it is an array of - // bitsets, and it if is, we OR all those. if (!isExpression) { + // do a deep copy -- Jmol 14.3.16 fixed[j] = SV.newV(T.varray, SV.deepCopy(v, false)); break; } + // if v is a list, we check to to see if it is an array of + // bitsets, and it if is, we OR all those. Lst<SV> sv = (Lst<SV>) v; BS bs = null; for (int k = 0; k < sv.size(); k++) { @@ -2554,6 +2563,7 @@ } fixed[j] = (bs == null ? SV.getVariable(v) : T.o(T.bitset, bs)); } else { + // assume we want a center P3 center = getObjectCenter(var, Integer.MIN_VALUE, Integer.MIN_VALUE); if (center == null) invArg(); Modified: trunk/Jmol/src/org/jmol/viewer/Jmol.properties =================================================================== --- trunk/Jmol/src/org/jmol/viewer/Jmol.properties 2015-09-22 04:53:25 UTC (rev 20788) +++ trunk/Jmol/src/org/jmol/viewer/Jmol.properties 2015-09-22 12:17:07 UTC (rev 20789) @@ -59,32 +59,30 @@ TODO: image (not found) stops JSmol -Jmol.___JmolVersion="14.3.16_2015.09.21b" +Jmol.___JmolVersion="14.3.16_2015.09.22" +bug fix: x.format("JSON") fails for recursive x + -- arrays or associative arrays can be recursive + -- detection of recursion now delivers empty array or associative array + -- example: + + $ a = [[1,2],3] + $ a..2 = a + $ print a.format("JSON") + + [ [ 1,2 ],[ [ 1,2 ],[ ] ] ] + + $ a = [b:1] + $ a.b = a + $ print a.format("JSON") + + { "b": { "b": { } } } + new feature: x = @a -- deep copy for a = array or associative array -- @a for string variable still gets the value of the variable named by variable a - -note: "deepCopy": - - function deepCopy(a) { - switch (a.type) { - case "hash": - var b = {}; - for (var key in a) - b[key] = deepCopy(a[key]); - return b; - case "array": - var b = []; - for (var j = a.length; j > 0; --j) - b[j] = deepCopy(a[j]); - return b; - default: - return a; - } -} - - + -- math environment only, not SELECT + new feature: for allows one continuation line, as in JavaScript and Java -- for example: for (i = 1; i <= 3; i++) 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