commit cb1c91fbac75a952ff4ddbd01adf39df1c81d435
parent b9d59e1774d94fa691cdb8921e1d97c1634f1ce4
Author: tomas <tomas@logand.com>
Date:   Sat, 23 Jan 2010 14:27:50 +0100
Changes from 2009-06-27
Diffstat:
| M | wps.js |  |  | 275 | ++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------- | 
1 file changed, 174 insertions(+), 101 deletions(-)
diff --git a/wps.js b/wps.js
@@ -1,5 +1,3 @@
-// TODO one run, exec function or name !quoted
-
 function isQuoted(V) {
   return V.q;
 }
@@ -39,7 +37,7 @@ function inDs(Ds, K) {
   return false;
 }
 
-function ps0(L, Os, Ds) { // TODO Nd name dict name=>sym?
+function ps0(L, Os, Ds, Es) { // TODO Nd name dict name=>sym?
   var N = L.length;
   var I = 0;
 
@@ -97,7 +95,7 @@ function ps0(L, Os, Ds) { // TODO Nd name dict name=>sym?
     // TODO 1e10 1E-5 real numbers
     // TODO radix numbers 8#1777 16#FFFE 2#1000
     var C = xchar();
-    if(member(C, "()<>/% \t\n")) throw "Symbol expected";
+    if(member(C, "()<>/% \t\n")) throw "Symbol expected, got " + C;
     var N = member(C, "+-0123456789.");
     var F = "." == C;
     var L = [C];
@@ -118,7 +116,7 @@ function ps0(L, Os, Ds) { // TODO Nd name dict name=>sym?
 
   function token() {
     skip();
-    switch(peek()) { // TODO read dict in <> <~~> <<>>
+    switch(peek()) { // TODO read dict in <> <~~> <<>> immediate literal //
       case false: return undefined;
       case "%": return comment();
       case "[": return new Symbol(xchar());
@@ -127,59 +125,72 @@ function ps0(L, Os, Ds) { // TODO Nd name dict name=>sym?
       case "}": D--; return new Symbol(xchar());
       case "/": xchar(); var X = symbol(); return quote(X);
       case "(": return text();
+      case "<":
+        xchar();
+        if("<" != peek()) throw "Encoded strings not implemented yet";
+        xchar();
+        return new Symbol("<<");
+      case ">":
+        xchar();
+        if(">" != peek()) throw "Unexpected >";
+        xchar();
+        return new Symbol(">>");
       default: return symbol();
     }
   }
 
-//   var Es = [];
+  function Xexec() {Es.push([false, Os.pop()]);};
 
-  function exec() {
-    var X = Os.pop();
+  function run(X, Z) {
     if(isSymbol(X) && !isQuoted(X)) { // executable name
       var K = symbolName(X);
+//       if("repeat" == K) {
+//         alert("" + inDs(Ds, "def")["setrgbcolor"][1] + "XXX: " + Os + " Z: " + Z);
+//       }
       var D = inDs(Ds, K);
       var V = D && D[K];
-      if(V) {
-        Os.push(V);
-        exec();
-//         Es.push(V);
-//         if("function" == typeof V) V();
-//         //else Os.push(V);
-//         else run(V);
-      } else throw "Unknown operator 1 '" + K + "'";
-    } else if(isArray(X) && isQuoted(X)) { // proc
-      var M = X.length;
-      for(var I = 0; I < M; I++) {
-        //Es.push(X[I]);
-        Os.push(X[I]);
-        exec();
+      if(V || V === 0) Es.push([false, V]);
+      else throw "Unknown operator '" + K + "'";
+    } else if(Z && isArray(X) && isQuoted(X)) { // proc from Es
+      if(0 < X.length) {
+        var F = X[0];
+        var R = quote(X.slice(1));
+        if(0 < R.length) Es.push([false, R, Xexec]);
+        //if(isSymbol(X) && !isQuoted(X)) Es.push([false, F]);
+        //else Os.push(F);
+        //alert(R.map(function(E) {return E.nm;}) + "\n" + F.nm);
+        run(F, false);
       }
     } else if("function" == typeof X) X(); // operator
     else Os.push(X);
   }
 
-//   function run(T) {
-//     if(T || T == 0) {
-// //       if(isSymbol(T) && !isQuoted(T)) {
-// //         var K = symbolName(T);
-// //         var D = inDs(Ds, K);
-// //         var V = D && D[K];
-// //         if(V) {
-// //           if("function" == typeof V) V();
-// //           //else Os.push(V);
-// //           else run(V);
-// //         } else throw "Unknown operator 1 '" + K + "'";
-// //       } else Os.push(T);
-//     }
-//   }
+  function exec() {
+    var X = Os.pop();
+    run(X, false);
+  }
+
+  function step() {
+    var C = Es.pop();
+    var L = C.shift(); // TODO use for 'exit'
+    var X = C.pop();
+    for(var I = 0; I < C.length; I++)
+      Os.push(C[I]);
+    run(X, true);
+  }
 
   function parse() {
     while(peek()) {
       var T = token();
-      if(T || T == 0) {
+      if(T || T === 0) {
         Os.push(T);
-        if(D <= 0 || 1 == D && isSymbol(T) && "{" == symbolName(T))
+        if(D <= 0 || isSymbol(T) &&
+           (member(symbolName(T), "[]{}") ||
+            "<<" == symbolName(T) || ">>" == symbolName(T))) {
           exec();
+          while(0 < Es.length)
+            step();
+        }
       }
     }
     return Os;
@@ -192,6 +203,7 @@ function wps(E, T) {
   var Os = [];
   var Sd = {};
   var Ds = [Sd];
+  var Es = [];
 
   // trivial
   Sd[".true"] = function() {Os.push(true);};
@@ -207,8 +219,7 @@ function wps(E, T) {
   };
 
   // math
-  Sd["neg"] = function() {Os.push(-1 * Os.pop());};
-  Sd["add"] = function() {Os.push(Os.pop() + Os.pop());};
+  Sd["sub"] = function() {var X = Os.pop(); Os.push(Os.pop() - X);};
   Sd["mul"] = function() {Os.push(Os.pop() * Os.pop());};
   Sd["div"] = function() {var X = Os.pop(); Os.push(Os.pop() / X);};
   Sd["mod"] = function() {var X = Os.pop(); Os.push(Os.pop() % X);};
@@ -219,10 +230,21 @@ function wps(E, T) {
   Sd["counttomark"] = function() {
     var N = 0;
     for(var I = Os.length - 1; 0 <= I; I--)
-      if(M === Os[I]) return N;
+      if(M === Os[I]) return Os.push(N);
       else N++;
     throw "Mark not found";
   };
+  Sd["<<"] = Sd["mark"];
+  Sd[">>"] = function() {
+    var D = {};
+    while(0 < Os.length) {
+      var V = Os.pop();
+      if(M === V) return Os.push(D);
+      D[Os.pop()] = V;
+    }
+    throw "Mark not found";
+  };
+
   Sd["exch"] = function() {
     var Y = Os.pop();
     var X = Os.pop();
@@ -262,78 +284,48 @@ function wps(E, T) {
   Sd["astore"] = function() {
     var A = Os.pop();
     var N = A.length;
-    var X = Os.length - N;
-    for(var I = 0; I < N; I++)
-      A[I] = Os[X + I];
+    for(var I = N - 1; 0 <= I; I--)
+      A[I] = Os.pop();
+    Os.push(A);
   };
 
   Sd["eq"] = function() {var Y = Os.pop(); var X = Os.pop(); Os.push(X == Y);};
   Sd["lt"] = function() {var Y = Os.pop(); var X = Os.pop(); Os.push(X < Y);};
 
-  //Sd["not"] = function() {var X = Os.pop(); Os.push(X == undefined || X == false);};
-  //Sd[".nand"] = function() {Os.push(Sd["not"]() || Sd["not"]());};
+  function Xexec() {Es.push([false, Os.pop()]);};
 
+  Sd["exec"] = Xexec;
   Sd["ifelse"] = function() {
     var N = Os.pop();
     var P = Os.pop();
     var C = Os.pop();
-    if(C == true) run(P);
-    else run(N);
+    Es.push([false, C === true ? P : N, Xexec]);
   };
-  Sd["for"] = function() {
+  Sd["for"] = function Xfor() {
     var B = Os.pop();
     var L = Os.pop();
     var K = Os.pop();
     var J = Os.pop();
     if(K < 0) {
-      for(var I = J; L <= I; I += K) {
-        Os.push(I);
-        run(B);
-      }
+      if(L <= J + K) Es.push([true, J + K, K, L, B, Xfor]);
+      if(L <= J) Es.push([false, J, B, Xexec]);
     } else {
-      for(var I = J; I <= L; I += K) {
-        Os.push(I);
-        run(B);
-      }
+      if(J + K <= L) Es.push([true, J + K, K, L, B, Xfor]);
+      if(J <= L) Es.push([false, J, B, Xexec]);
     }
   };
+  Sd["repeat"] = function Xrepeat() {
+    var B = Os.pop();
+    var N = Os.pop();
+    if(1 < N) Es.push([true, N - 1, B, Xrepeat]);
+    if(0 < N) Es.push([false, B, Xexec]);
+  };
 
-  Sd["="] = function() {alert(Os.pop());};
+  Sd["="] = function() {var X = Os.pop(); alert(X.nm || X.length || X);};
   Sd["=="] = function() {alert(Os.pop());}; // TODO
   Sd["stack"] = function() {alert(Os);}; // TODO
   Sd["pstack"] = function() {alert(Os);}; // TODO
 
-//   function run1(T) {
-//     if(T || T == 0) {
-//       if(isSymbol(T) && !isQuoted(T)) {
-//         var K = symbolName(T);
-//         var D = inDs(Ds, K);
-//         var V = D && D[K];
-//         if(V) {
-//           if("function" == typeof V) V();
-//           //else Os.push(V);
-//           else run(V);
-//         } else throw "Unknown operator 1 '" + K + "'";
-//       } else Os.push(T);
-//     }
-//   }
-
-//   function run(C) {
-//     if(!C.length) Os.push(C); // TODO run?
-//     else {
-//       var M = C.length;
-//       for(var I = 0; I < M; I++) {
-//         var T = C[I];
-//         run1(T);
-// //         if(isSymbol(T) && !isQuoted(T)) {
-// //           var X = symbolName(T);
-// //           if(Sd[X]) Sd[X]();
-// //           else throw "Missing operator '" + X + "'";
-// //         } else Os.push(T);
-//       }
-//     }
-//   }
-
   Sd["dict"] = function() {Os.pop(); Os.push({});};
   Sd["get"] = function() { // dict key -- any
     var K = Os.pop();
@@ -354,7 +346,7 @@ function wps(E, T) {
   Sd["end"] = function() {Ds.pop();};
   Sd["currentdict"] = function() {Os.push(Ds[Ds.length - 1]);};
   Sd["where"] = function() {
-    var K = Os.pop();
+    var K = symbolName(Os.pop());
     var D = inDs(Ds, K);
 	if(D) {
 	  Os.push(D);
@@ -362,21 +354,12 @@ function wps(E, T) {
 	} else Os.push(false);
   };
 
-//   Sd["def"] = function() {
-//     var C = Os.pop();
-//     var N = Os.pop();
-//     if(isSymbol(N) && isQuoted(N)) Sd[symbolName(N)] = function() {run(C);};
-//     else throw "Wrong operator name '" + N + "' as '" + typeof N
-//       + "' for '" + C + "'";
-//   };
-
   Sd["array"] = function() {Os.push(new Array(Os.pop()));};
 
   Sd["restore"] = function() {Os.pop();}; // TODO
   Sd["save"] = function() {Os.push([]);}; // TODO
 
   Sd["bind"] = function() {}; // TODO
-  Sd["load"] = function() {}; // TODO
 
   //////////////////////////////////////////////////////////
 
@@ -396,6 +379,9 @@ function wps(E, T) {
   Sd[".gc"] = function() { // -- gc
     Os.push(E.getContext("2d"));
   };
+  Sd[".date"] = function() { // -- date
+    Os.push(new Date());
+  };
 
   /////////////////////////////////////////////////////
 
@@ -416,8 +402,95 @@ function wps(E, T) {
     Os.push("rgba(" + R + "," + G + "," + B + "," + A + ")");
   };
 
+  Sd[".xy"] = function() { // x y m -- x' y'
+    var M = Os.pop();
+    var Y = Os.pop();
+    var X = Os.pop();
+    Os.push(M[0] * X + M[2] * Y + M[4]);
+    Os.push(M[1] * X + M[3] * Y + M[5]);
+  };
+  Sd["translate"] = function() {
+	var A = Os.pop();
+	var B = Os.pop();
+	if(typeof A == "object") Os.push([1, 0, 0, 1, Os.pop(), B]);
+    else {
+	  var M = [1, 0, 0, 1, B, A];
+	  CTMupdate(M);
+	  E.getContext("2d").translate(B, A);
+	}
+  };
+  Sd["rotate"] = function() {
+	var A = Os.pop();
+	if(typeof A == "object") {
+	  var B = opStack.pop();
+      Os.push([Math.cos(d2r(B)), Math.sin(d2r(B)),
+               -1 * Math.sin(d2r(B)), Math.cos(d2r(B)),
+               0, 0]);
+	} else {
+	  var M = [Math.cos(d2r(A)), Math.sin(d2r(A)),
+               -1 * Math.sin(d2r(A)), Math.cos(d2r(A)),
+               0, 0];
+      CTMupdate(M);
+	  //E.getContext("2d").rotate(d2r(A));
+	  E.getContext("2d").rotate(A);
+	}
+  };
+  Sd["scale"] = function() {
+	var A = Os.pop();
+	var B = Os.pop();
+	if(typeof A == "object") Os.push([Os.pop(), 0, 0, B, 0, 0]);
+    else {
+	  var M = [B, 0, 0, A, 0, 0,1];
+	  CTMupdate(M);
+	  ctx.scale(B, A);
+	}
+  };
+  Sd["transform"] = function() {
+	var A = Os.pop();
+    Os.push(A);
+	if(typeof A != "object")
+      Sd[".tm"]();
+    Sd[".xy"]();
+  };
+  Sd["itransform"] = function() {
+	var A = Os.pop();
+	if(typeof A == "object") Os.push(inverse(A));
+    else {
+      Os.push(A);
+      Sd[".tm"]();
+	  var M = Os.pop();
+      Os.push(inverse(M));
+    }
+    Sd[".xy"]();
+  };
+  Sd["rlineto"] = function() {
+	var Y = Os.pop();
+	var X = Os.pop();
+// 	pathY += yUnderMatrix(offX,offY,CTMdelta);
+// 	pathX += xUnderMatrix(offX,offY,CTMdelta);
+// 	var iCTMdelta = CTMdelta.inverse();
+// 	currentX = xUnderMatrix(pathX,pathY,iCTMdelta);
+// 	currentY = yUnderMatrix(pathX,pathY,iCTMdelta);
+// 	pathX=currentX;
+// 	pathY=currentY;
+// 	CTMdelta = CTMident;
+
+ 	//ctx.lineTo(X, Y);
+  };
+  function d2r(A) {
+    return Math.PI / 180 * A;
+  }
+  function CTMupdate(M) {
+// 	currentX = xUnderMatrix(currentX,currentY,mat);
+// 	currentY = yUnderMatrix(currentX,currentY,mat);
+// 		CTMdelta = CTMdelta.timesMatrix(mat);
+// 		CTM = CTM.timesMatrix(mat);
+  }
+
+
+
   if(T.length)
     for(var I = 0; I < T.length; I++)
-      ps0(T[I], Os, Ds);
-  else ps0(T, Os, Ds);
+      ps0(T[I], Os, Ds, Es);
+  else ps0(T, Os, Ds, Es);
 }