commit 77e4b7197e2fc042ce2822b0fcfd90a8b5ce5ab9
parent fc8c5c8788b4e02d076e66296c94ca45881f6fbf
Author: Alexander Burger <abu@software-lab.de>
Date:   Thu, 14 Jul 2011 08:26:20 +0200
'prop' and '::' cons default cell
Diffstat:
13 files changed, 175 insertions(+), 130 deletions(-)
diff --git a/CHANGES b/CHANGES
@@ -1,4 +1,5 @@
 * XXsep11 picoLisp-3.0.8
+   'prop' and '::' cons default cell
    "lib/test.l" position independent
    'hash' function
    Bug in 'dbFetchEX' for db extensions
diff --git a/doc/refP.html b/doc/refP.html
@@ -654,13 +654,14 @@ href="refP.html#prog1">prog1</a></code>.
 123-> 2
 </code></pre>
 
-<dt><a name="prop"><code>(prop 'sym1|lst ['sym2|cnt ..] 'sym) -> lst|sym</code></a>
+<dt><a name="prop"><code>(prop 'sym1|lst ['sym2|cnt ..] 'sym) -> var</code></a>
 <dd>Fetches a property for a property key <code>sym</code> from a symbol. That
 symbol is <code>sym1</code> (if no other arguments are given), or a symbol found
 by applying the <code><a href="refG.html#get">get</a></code> algorithm to
 <code>sym1|lst</code> and the following arguments. The property (the cell, not
-just its value) is returned, suitable for direct (destructive) manipulations.
-See also <code><a href="ref_.html#::">::</a></code>.
+just its value) is returned, suitable for direct (destructive) manipulations
+with functions expecting a <code>var</code> argument. See also <code><a
+href="ref_.html#::">::</a></code>.
 
 <pre><code>
 : (put 'X 'cnt 0)
diff --git a/doc/ref_.html b/doc/ref_.html
@@ -250,14 +250,15 @@ href="ref_.html#;">;</a></code>, <code><a href="ref_.html#=:">=:</a></code> and
 -> 1
 </code></pre>
 
-<dt><a name="::"><code>(:: sym [sym1|cnt .. sym2]) -> lst|sym</code></a>
+<dt><a name="::"><code>(:: sym [sym1|cnt .. sym2]) -> var</code></a>
 <dd>Fetches a property for a property key <code>sym</code> or <code>sym2</code>
 from a symbol. That symbol is <code>This</code> (if no other arguments are
 given), or a symbol found by applying the <code><a
 href="refG.html#get">get</a></code> algorithm to <code>This</code> and the
 following arguments. The property (the cell, not just its value) is returned,
-suitable for direct (destructive) manipulations. Used typically in methods or
-<code><a href="refW.html#with">with</a></code> bodies. See also <code><a
+suitable for direct (destructive) manipulations with functions expecting a
+<code>var</code> argument. Used typically in methods or <code><a
+href="refW.html#with">with</a></code> bodies. See also <code><a
 href="ref_.html#=:">=:</a></code>, <code><a
 href="refP.html#prop">prop</a></code> and <code><a
 href="ref_.html#:">:</a></code>.
diff --git a/ersatz/fun.src b/ersatz/fun.src
@@ -1,4 +1,4 @@
-# 09jul11abu
+# 14jul11abu
 # (c) Software Lab. Alexander Burger
 
 # Ersatz PicoLisp Functions
@@ -1990,7 +1990,7 @@ get (x)
       x = x.get(ex.Car.eval());
    return x;
 
-# (prop 'sym1|lst ['sym2|cnt ..] 'sym) -> lst|sym
+# (prop 'sym1|lst ['sym2|cnt ..] 'sym) -> var
 prop (x)
    x = (ex = ex.Cdr).Car.eval();
    while ((ex = ex.Cdr).Cdr instanceof Cell)
@@ -2021,7 +2021,7 @@ prop (x)
    while (ex.Cdr instanceof Cell);
    return x;
 
-# (:: sym|0 [sym1|cnt .. sym2]) -> lst|sym
+# (:: sym|0 [sym1|cnt .. sym2]) -> var
 :: (x)
    x = This.Car;
    while ((ex = ex.Cdr).Cdr instanceof Cell)
diff --git a/ersatz/picolisp.jar b/ersatz/picolisp.jar
Binary files differ.
diff --git a/ersatz/sys.src b/ersatz/sys.src
@@ -1,4 +1,4 @@
-// 09jul11abu
+// 13jul11abu
 // (c) Software Lab. Alexander Burger
 
 import java.util.*;
@@ -2179,7 +2179,7 @@ public class PicoLisp {
                   System.arraycopy(Prop, 0, a, 0, p);
                   Prop = a;
                }
-               Prop[p] = val != T? new Cell(val, key): key;
+               Prop[p] = val != T? new Cell(val, key) : key;
             }
          }
          else if (val != Nil)
@@ -2208,21 +2208,30 @@ public class PicoLisp {
       }
 
       final Any prop(Any key) {
-         if (Prop == null)
-            return Nil;
          Any x;
-         int i = Prop.length;
+
+         if (Prop == null) {
+            (Prop = new Any[3])[2] = x = new Cell(Nil, key);
+            return x;
+         }
+         int i = Prop.length, p = -1;
          do {
-            if ((x = Prop[--i]) != null) {
-               if (x instanceof Cell) {
-                  if (key == x.Cdr)
-                     return x;
-               }
-               else if (key == x)
-                  return key;
+            if ((x = Prop[--i]) == null)
+               p = i;
+            else if (x instanceof Cell) {
+               if (key == x.Cdr)
+                  return x;
             }
+            else if (key == x)
+               return key;
          } while (i != 0);
-         return Nil;
+         if (p < 0) {
+            Any[] a = new Any[(p = Prop.length) * 2];
+            System.arraycopy(Prop, 0, a, 0, p);
+            Prop = a;
+         }
+         Prop[p] = x = new Cell(Nil, key);
+         return x;
       }
 
       final Any putl(Any lst) {
diff --git a/lib/db.l b/lib/db.l
@@ -1,4 +1,4 @@
-# 06jun11abu
+# 13jul11abu
 # (c) Software Lab. Alexander Burger
 
 # *Dbs *Jnl *Blob upd
@@ -835,9 +835,7 @@
 (de inc! (Obj Var Val)
    (when (num? (get Obj Var))
       (dbSync)
-      (prog2
-         (touch Obj)
-         (inc (prop Obj Var) (or Val 1))
+      (prog1 (inc (prop Obj Var) (or Val 1))
          (commit 'upd) ) ) )
 
 (de blob! (Obj Var File)
@@ -916,7 +914,6 @@
 
 (dm inc> (Var Val)
    (when (num? (get This Var))
-      (touch This)
       (let Old (get This Var)
          (rel> (meta This Var) This Old
             (inc (prop This Var) (or Val 1)) )
@@ -927,7 +924,6 @@
 (dm inc!> (Var Val)
    (when (num? (get This Var))
       (dbSync)
-      (touch This)
       (let Old (get This Var)
          (rel> (meta This Var) This Old
             (inc (prop This Var) (or Val 1)) )
@@ -938,7 +934,6 @@
 
 (dm dec> (Var Val)
    (when (num? (get This Var))
-      (touch This)
       (let Old (get This Var)
          (rel> (meta This Var) This Old
             (dec (prop This Var) (or Val 1)) )
@@ -949,7 +944,6 @@
 (dm dec!> (Var Val)
    (when (num? (get This Var))
       (dbSync)
-      (touch This)
       (let Old (get This Var)
          (rel> (meta This Var) This Old
             (dec (prop This Var) (or Val 1)) )
diff --git a/lib/tags b/lib/tags
@@ -8,15 +8,15 @@ $ (2953 . "@src64/flow.l")
 - (2209 . "@src64/big.l")
 -> (3913 . "@src64/subr.l")
 / (2511 . "@src64/big.l")
-: (2896 . "@src64/sym.l")
-:: (2920 . "@src64/sym.l")
-; (2822 . "@src64/sym.l")
+: (2916 . "@src64/sym.l")
+:: (2940 . "@src64/sym.l")
+; (2842 . "@src64/sym.l")
 < (2207 . "@src64/subr.l")
 <= (2237 . "@src64/subr.l")
 <> (2144 . "@src64/subr.l")
 = (2115 . "@src64/subr.l")
 =0 (2173 . "@src64/subr.l")
-=: (2851 . "@src64/sym.l")
+=: (2871 . "@src64/sym.l")
 == (2059 . "@src64/subr.l")
 ==== (965 . "@src64/sym.l")
 =T (2181 . "@src64/subr.l")
@@ -138,7 +138,7 @@ fish (1613 . "@src64/apply.l")
 flg? (2445 . "@src64/subr.l")
 flip (1699 . "@src64/subr.l")
 flush (5070 . "@src64/io.l")
-fold (3341 . "@src64/sym.l")
+fold (3371 . "@src64/sym.l")
 for (2222 . "@src64/flow.l")
 fork (3256 . "@src64/flow.l")
 format (2089 . "@src64/big.l")
@@ -148,9 +148,9 @@ full (1075 . "@src64/subr.l")
 fun? (732 . "@src64/sym.l")
 gc (432 . "@src64/gc.l")
 ge0 (2705 . "@src64/big.l")
-get (2748 . "@src64/sym.l")
+get (2766 . "@src64/sym.l")
 getd (740 . "@src64/sym.l")
-getl (3030 . "@src64/sym.l")
+getl (3060 . "@src64/sym.l")
 glue (1232 . "@src64/sym.l")
 gt0 (2716 . "@src64/big.l")
 hash (2974 . "@src64/big.l")
@@ -190,8 +190,8 @@ lit (155 . "@src64/flow.l")
 load (4133 . "@src64/io.l")
 lock (1182 . "@src64/db.l")
 loop (2165 . "@src64/flow.l")
-low? (3213 . "@src64/sym.l")
-lowc (3243 . "@src64/sym.l")
+low? (3243 . "@src64/sym.l")
+lowc (3273 . "@src64/sym.l")
 lst? (2415 . "@src64/subr.l")
 lt0 (2680 . "@src64/big.l")
 lup (2224 . "@src64/sym.l")
@@ -210,7 +210,7 @@ max (2327 . "@src64/subr.l")
 maxi (1511 . "@src64/apply.l")
 member (2455 . "@src64/subr.l")
 memq (2477 . "@src64/subr.l")
-meta (3133 . "@src64/sym.l")
+meta (3163 . "@src64/sym.l")
 meth (1084 . "@src64/flow.l")
 method (1048 . "@src64/flow.l")
 min (2356 . "@src64/subr.l")
@@ -265,13 +265,13 @@ prior (2713 . "@src64/subr.l")
 prog (1752 . "@src64/flow.l")
 prog1 (1760 . "@src64/flow.l")
 prog2 (1777 . "@src64/flow.l")
-prop (2779 . "@src64/sym.l")
+prop (2797 . "@src64/sym.l")
 protect (517 . "@src64/main.l")
 prove (3527 . "@src64/subr.l")
 push (1686 . "@src64/sym.l")
 push1 (1722 . "@src64/sym.l")
-put (2696 . "@src64/sym.l")
-putl (2948 . "@src64/sym.l")
+put (2714 . "@src64/sym.l")
+putl (2978 . "@src64/sym.l")
 pwd (2675 . "@src64/main.l")
 queue (1918 . "@src64/sym.l")
 quit (1090 . "@src64/main.l")
@@ -333,8 +333,8 @@ unify (3935 . "@src64/subr.l")
 unless (1893 . "@src64/flow.l")
 until (2077 . "@src64/flow.l")
 up (698 . "@src64/main.l")
-upp? (3228 . "@src64/sym.l")
-uppc (3292 . "@src64/sym.l")
+upp? (3258 . "@src64/sym.l")
+uppc (3322 . "@src64/sym.l")
 use (1565 . "@src64/flow.l")
 usec (2663 . "@src64/main.l")
 val (1461 . "@src64/sym.l")
@@ -342,7 +342,7 @@ version (3048 . "@src64/main.l")
 wait (3118 . "@src64/io.l")
 when (1876 . "@src64/flow.l")
 while (2053 . "@src64/flow.l")
-wipe (3088 . "@src64/sym.l")
+wipe (3118 . "@src64/sym.l")
 with (1322 . "@src64/flow.l")
 wr (5195 . "@src64/io.l")
 xchg (1536 . "@src64/sym.l")
diff --git a/src/sym.c b/src/sym.c
@@ -1,4 +1,4 @@
-/* 25oct10abu
+/* 14jul11abu
  * (c) Software Lab. Alexander Burger
  */
 
@@ -1056,28 +1056,29 @@ any get(any x, any key) {
 any prop(any x, any key) {
    any y, z;
 
-   if (!isCell(y = tail1(x)))
-      return Nil;
-   if (!isCell(car(y))) {
-      if (key == car(y))
-         return key;
-   }
-   else if (key == cdar(y))
-      return car(y);
-   while (isCell(z = cdr(y))) {
-      if (!isCell(car(z))) {
-         if (key == car(z)) {
-            cdr(y) = cdr(z),  cdr(z) = tail1(x),  Tail(x, z);
+   if (isCell(y = tail1(x))) {
+      if (!isCell(car(y))) {
+         if (key == car(y))
             return key;
-         }
       }
-      else if (key == cdar(z)) {
-         cdr(y) = cdr(z),  cdr(z) = tail1(x),  Tail(x, z);
-         return car(z);
+      else if (key == cdar(y))
+         return car(y);
+      while (isCell(z = cdr(y))) {
+         if (!isCell(car(z))) {
+            if (key == car(z)) {
+               cdr(y) = cdr(z),  cdr(z) = tail1(x),  Tail(x, z);
+               return key;
+            }
+         }
+         else if (key == cdar(z)) {
+            cdr(y) = cdr(z),  cdr(z) = tail1(x),  Tail(x, z);
+            return car(z);
+         }
+         y = z;
       }
-      y = z;
    }
-   return Nil;
+   Tail(x, cons(y = cons(Nil,key), tail1(x)));
+   return y;
 }
 
 // (put 'sym1|lst ['sym2|cnt ..] 'sym|0 'any) -> any
@@ -1131,7 +1132,7 @@ any doGet(any ex) {
    return Pop(c1);
 }
 
-// (prop 'sym1|lst ['sym2|cnt ..] 'sym) -> lst|sym
+// (prop 'sym1|lst ['sym2|cnt ..] 'sym) -> var
 any doProp(any ex) {
    any x;
    cell c1, c2;
@@ -1149,7 +1150,8 @@ any doProp(any ex) {
       data(c2) = EVAL(car(x));
    }
    NeedSym(ex,data(c1));
-   Fetch(ex,data(c1));
+   CheckNil(ex,data(c1));
+   Touch(ex,data(c1));
    return prop(Pop(c1), data(c2));
 }
 
@@ -1224,7 +1226,7 @@ any doCol(any ex) {
    return y;
 }
 
-// (:: sym|0 [sym1|cnt .. sym2]) -> lst|sym
+// (:: sym|0 [sym1|cnt .. sym2]) -> var
 any doPropCol(any ex) {
    any x, y;
 
@@ -1242,6 +1244,9 @@ any doPropCol(any ex) {
          }
       }
    }
+   NeedSym(ex,y);
+   CheckNil(ex,y);
+   Touch(ex,y);
    return prop(y, car(x));
 }
 
diff --git a/src/vers.h b/src/vers.h
@@ -1 +1 @@
-static byte Version[4] = {3,0,7,2};
+static byte Version[4] = {3,0,7,3};
diff --git a/src64/sym.l b/src64/sym.l
@@ -1,4 +1,4 @@
-# 28mar11abu
+# 14jul11abu
 # (c) Software Lab. Alexander Burger
 
 ### Compare long names ###
@@ -2622,73 +2622,91 @@
    ret
 
 (code 'propEC_E 0)
-   ld A (E TAIL)  # Get tail
-   num A  # No properties?
-   jnz retNil  # Return NIL
-   off A SYM  # Clear 'extern' tag
-   atom (A)  # First property atomic?
-   if nz  # Yes
-      cmp C (A)  # Found flag?
-      if eq  # Yes
-         ld E C  # Return key
-         ret
-      end
-   else
-      cmp C ((A) CDR)  # Found property?
-      if eq  # Yes
-         ld E (A)  # Return property
-         ret
-      end
-   end
    push X
-   do
-      ld X (A CDR)  # Next property
-      atom X  # Any?
-   while z  # Yes
-      atom (X)  # Atomic?
+   ld A (E TAIL)  # Get tail
+   num A  # Properties?
+   if z  # Yes
+      off A SYM  # Clear 'extern' tag
+      atom (A)  # First property atomic?
       if nz  # Yes
-         cmp C (X)  # Found flag?
+         cmp C (A)  # Found flag?
          if eq  # Yes
-            ld (A CDR) (X CDR)  # Unlink cell
-            ld A (E TAIL)  # Get tail
-            sym A  # Extern?
-            if z  # No
-               ld (X CDR) A  # Insert cell in front
-            else
-               off A SYM  # Clear 'extern' tag
-               ld (X CDR) A  # Insert cell in front
-               or X SYM  # Set 'extern' tag
-            end
-            ld (E TAIL) X
             ld E C  # Return key
             pop X
             ret
          end
       else
-         cmp C ((X) CDR)  # Found property?
+         cmp C ((A) CDR)  # Found property?
          if eq  # Yes
-            ld (A CDR) (X CDR)  # Unlink cell
-            ld A (E TAIL)  # Get tail
-            sym A  # Extern?
-            if z  # No
-               ld (X CDR) A  # Insert cell in front
-               ld (E TAIL) X
-               ld E (X)  # Return property
-            else
-               off A SYM  # Clear 'extern' tag
-               ld (X CDR) A  # Insert cell in front
-               ld A (X)  # Return property
-               or X SYM  # Set 'extern' tag
-               ld (E TAIL) X
-               ld E A
-            end
+            ld E (A)  # Return property
             pop X
             ret
          end
       end
-      ld A X
-   loop
-   ld E Nil  # Return NIL
+      do
+         ld X (A CDR)  # Next property
+         atom X  # Any?
+      while z  # Yes
+         atom (X)  # Atomic?
+         if nz  # Yes
+            cmp C (X)  # Found flag?
+            if eq  # Yes
+               ld (A CDR) (X CDR)  # Unlink cell
+               ld A (E TAIL)  # Get tail
+               sym A  # Extern?
+               if z  # No
+                  ld (X CDR) A  # Insert cell in front
+               else
+                  off A SYM  # Clear 'extern' tag
+                  ld (X CDR) A  # Insert cell in front
+                  or X SYM  # Set 'extern' tag
+               end
+               ld (E TAIL) X
+               ld E C  # Return key
+               pop X
+               ret
+            end
+         else
+            cmp C ((X) CDR)  # Found property?
+            if eq  # Yes
+               ld (A CDR) (X CDR)  # Unlink cell
+               ld A (E TAIL)  # Get tail
+               sym A  # Extern?
+               if z  # No
+                  ld (X CDR) A  # Insert cell in front
+                  ld (E TAIL) X
+                  ld E (X)  # Return property
+               else
+                  off A SYM  # Clear 'extern' tag
+                  ld (X CDR) A  # Insert cell in front
+                  ld A (X)  # Return property
+                  or X SYM  # Set 'extern' tag
+                  ld (E TAIL) X
+                  ld E A
+               end
+               pop X
+               ret
+            end
+         end
+         ld A X
+      loop
+   end
+   call cons_A  # New property cell
+   ld (A) Nil  # (NIL . key)
+   ld (A CDR) C
+   call consA_C  # New first property
+   ld (C) A
+   ld X (E TAIL)  # Get tail
+   sym X  # Extern?
+   if z  # No
+      ld (C CDR) X
+   else
+      off X SYM  # Clear 'extern' tag
+      ld (C CDR) X
+      or C SYM  # Set 'extern' tag
+   end
+   ld (E TAIL) C  # Set new tail
+   ld E A  # Return first (new) cell
    pop X
    ret
 
@@ -2775,7 +2793,7 @@
    pop X
    ret
 
-# (prop 'sym1|lst ['sym2|cnt ..] 'sym) -> lst|sym
+# (prop 'sym1|lst ['sym2|cnt ..] 'sym) -> var
 (code 'doProp 2)
    push X
    push Y
@@ -2807,9 +2825,11 @@
    jnz symErrEX
    sym E
    jz symErrEX
+   cmp E Nil  # Can't be NIL
+   jeq protErrEX
    sym (E TAIL)  # External symbol?
    if nz  # Yes
-      call dbFetchEX  # Fetch it
+      call dbTouchEX  # Touch it
    end
    ld C (L I)  # Get key
    call propEC_E
@@ -2916,7 +2936,7 @@
    pop X
    ret
 
-# (:: sym|0 [sym1|cnt .. sym2]) -> lst|sym
+# (:: sym|0 [sym1|cnt .. sym2]) -> var
 (code 'doPropCol 2)
    push X
    push Y
@@ -2939,6 +2959,16 @@
          call getnECX_E
       loop
    end
+   num E  # Need symbol
+   jnz symErrEX
+   sym E
+   jz symErrEX
+   cmp E Nil  # Can't be NIL
+   jeq protErrEX
+   sym (E TAIL)  # External symbol?
+   if nz  # Yes
+      call dbTouchEX  # Touch it
+   end
    call propEC_E
    pop Y
    pop X
diff --git a/src64/version.l b/src64/version.l
@@ -1,6 +1,6 @@
-# 08jul11abu
+# 14jul11abu
 # (c) Software Lab. Alexander Burger
 
-(de *Version 3 0 7 2)
+(de *Version 3 0 7 3)
 
 # vi:et:ts=3:sw=3
diff --git a/test/src/sym.l b/test/src/sym.l
@@ -1,4 +1,4 @@
-# 09sep09abu
+# 13jul11abu
 # (c) Software Lab. Alexander Burger
 
 ### name ###
@@ -267,6 +267,7 @@
    (put A 'x 1)
    (put B 'a 'y 2)
    (put C 0 -1 'a 'z 3)
+   (test '(NIL . p) (prop 'A 'p))
    (test 1 (get A 'x))
    (test 1 (; A x))
    (test 2 (with A (: y)))
@@ -281,6 +282,9 @@
    (test 3 (get C 0 1 'z))
    (test 3 (get C 0 -1 'a 'z))
    (test 3 (; C 0 -1 a z))
+   (test 1 (push (prop 'A 'p) 1))
+   (test 1 (with 'A (pop (:: p))))
+   (test NIL (get 'A 'p))
    (test (3 . z) (prop C 0 -1 'a 'z))
    (test 9 (with C (=: 0 -1 a z (* 3 3))))
    (test (9 . z) (with C (:: 0 -1 a z)))