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

Reply via email to