2003/06/26 01:53:37
authorbrian <brian@xwt.org>
Fri, 30 Jan 2004 07:02:23 +0000 (07:02 +0000)
committerbrian <brian@xwt.org>
Fri, 30 Jan 2004 07:02:23 +0000 (07:02 +0000)
darcs-hash:20040130070223-aa32f-c94f6d23b99c7b1014902d12d729f820a266fc58.gz

src/org/xwt/Template.java
src/org/xwt/XMLRPC.java
src/org/xwt/js/ArrayImpl.java
src/org/xwt/js/CompiledFunctionImpl.java
src/org/xwt/js/JS.java
src/org/xwt/js/Lexer.java
src/org/xwt/js/Parser.java

index c1a2532..6ee6f0b 100644 (file)
@@ -488,6 +488,7 @@ public class Template {
                     if (t.redirect != null)
                         throw new XML.SchemaException("the <redirect> header element may not appear more than once");
                     t.redirect = c.vals[0].toString();
+                    if(t.redirect.equals("null")) t.redirect = null;
                     return;
 
                 } else if (c.localName.equals("preapply")) {
index 282d9ef..c4f5fc6 100644 (file)
@@ -386,8 +386,8 @@ class XMLRPC extends JS.Callable {
     }
 
     /** When you get a property from an XMLRPC, it just returns another XMLRPC with the property name tacked onto methodname. */
-    public Object get(String name) {
-        return new XMLRPC(url, (methodname.equals("") ? "" : methodname + ".") + name, http);
+    public Object get(Object name) {
+        return new XMLRPC(url, (methodname.equals("") ? "" : methodname + ".") + name.toString(), http);
     }
 
     public XMLRPC(String url, String methodname) {
index 40bc873..ab63633 100644 (file)
@@ -29,6 +29,19 @@ class ArrayImpl extends JS.Obj {
         if (key.equals("cascade")) return org.xwt.Trap.cascadeFunction;
         if (key.equals("trapee")) return org.xwt.Trap.currentTrapee();
         if (key.equals("length")) return new Long(vec.size());
+        if (key.equals("push")) return new JS.Callable() {
+            public Object call(JS.Array args) {
+                for(int i=0;i<args.length();i++)
+                    vec.push(args.elementAt(i));
+                return new Long(vec.size());
+            }
+        };
+        if (key.equals("pop")) return new JS.Callable() {
+            public Object call(JS.Array args) {
+                return vec.pop(); // this'll return null on size()==0 
+            }
+        };
+                
         int i = intVal(key);
         if (i == Integer.MIN_VALUE) return super.get(key);
         try {
index 09374a3..366ff8c 100644 (file)
@@ -223,7 +223,7 @@ class CompiledFunctionImpl extends JSCallable implements ByteCodes, Tokens {
                 }
                 Object ret = null;
                 if (o == null) throw je("tried to get property \"" + v + "\" from the null value");
-                if (v == null) throw je("tried to get the null key from " + v);
+                if (v == null) throw je("tried to get the null key from " + o);
                 if (o instanceof String) {
                     ret = getFromString((String)o, v);
                 } else if (o instanceof Boolean) {
@@ -331,6 +331,7 @@ class CompiledFunctionImpl extends JSCallable implements ByteCodes, Tokens {
                     boolean ret;
                     if (l == null) { Object tmp = r; r = l; l = tmp; }
                     if (l == null && r == null) ret = true;
+                    else if (r == null) ret = false; // l != null, so its false
                     else if (l instanceof Boolean) ret = new Boolean(JS.toBoolean(r)).equals(l);
                     else if (l instanceof Number) ret = JS.toNumber(r).doubleValue() == JS.toNumber(l).doubleValue();
                     else if (l instanceof String) ret = r != null && l.equals(r.toString());
@@ -379,6 +380,38 @@ class CompiledFunctionImpl extends JSCallable implements ByteCodes, Tokens {
                     if (args.length() != 1) return null;
                     return new Integer(((String)o).indexOf(args.elementAt(0).toString()));
                 } };
+        // This is just a quick and dirty split implementation. its could be optimized a lot and it doesn't 
+        // do regexps yet. this will need to be rewritten when we get regexp support anyway
+        else if (v.equals("split")) return new JS.Callable() {
+                public Object call(JS.Array args) {
+                    String sep;
+                    int limit, s,p,matches=0;
+                    int seplen;
+                    JS.Array ret;
+                    
+                    if(args.length() > 1) limit = JS.toNumber(args.elementAt(1)).intValue();
+                    else limit = 0;
+                    if(args.length() > 0) sep = args.elementAt(0).toString();
+                    else sep = null;
+                    
+                    seplen = sep!=null ? sep.length() : 0;
+                     
+                    // special case sep == null, split up chars
+                    if(seplen == 0) {
+                        ret = new JS.Array(o.length());
+                        for(int i=0;i<o.length();i++) ret.setElementAt(o.substring(i,i+1),i);
+                        return ret;
+                    }
+                    ret = new JS.Array();
+                    for(s=0;(limit<=0 || matches < limit-1) && (p = o.indexOf(sep,s)) != -1;s=p+seplen) {
+                        ret.addElement(o.substring(s,p));
+                        matches++;
+                    }
+                    if(s != o.length()) ret.addElement(o.substring(s));
+                    return ret;
+                } };
+                        
+                        
         throw new JS.Exn("Not Implemented: propery " + v + " on String objects");
     }
 
index 77d95cc..be82e70 100644 (file)
@@ -27,7 +27,14 @@ public abstract class JS {
     public static boolean toBoolean(Object o) {
         if (o == null) return false;
         if (o instanceof Boolean) return ((Boolean)o).booleanValue();
-        if (o instanceof Number) return o.equals(new Integer(0));
+        if (o instanceof Long) return ((Long)o).longValue() != 0;
+        if (o instanceof Integer) return ((Integer)o).intValue() != 0;
+        if (o instanceof Number) {
+            double d = ((Number) o).doubleValue();
+            // NOTE: d == d is a test for NaN. It should be faster than Double.isNaN()
+            return d != 0.0 && d == d;
+        }
+        if (o instanceof String) return ((String)o).length() != 0;
         return true;
     }
 
@@ -41,10 +48,12 @@ public abstract class JS {
     public static Number toNumber(Object o) {
         if (o == null) return new Long(0);
         if (o instanceof Number) return ((Number)o);
-        if (o instanceof String) try { return new Double((String)o); } catch (NumberFormatException e) { return new Double(0); }
+        // FIXME: There are about 3 pages of rules in ecma262 about string to number conversions
+        // We aren't even close to following all those rules
+        if (o instanceof String) try { return new Double((String)o); } catch (NumberFormatException e) { return new Double(Double.NaN); }
         if (o instanceof Boolean) return ((Boolean)o).booleanValue() ? new Long(1) : new Long(0);
         if (o instanceof JS) return ((JS)o).coerceToNumber();
-        throw new Error("a " + o.getClass().getName() + " has no numeric value");
+        throw new Error("toNumber() got object of type " + o.getClass().getName() + " which we don't know how to handle");
     }
 
 
index f08ebce..81066bb 100644 (file)
@@ -342,6 +342,8 @@ class Lexer implements Tokens {
         public void unread() throws IOException { unread((char)lastread); }
         public void unread(char c) throws IOException {
             reader.unread(c);
+            if(c == '\n') col = -1;
+            else col--;
             if (accumulator != null) accumulator.setLength(accumulator.length() - 1);
         }
         public boolean match(char c) throws IOException { if (peek() == c) { reader.read(); return true; } else return false; }
@@ -354,7 +356,11 @@ class Lexer implements Tokens {
             lastread = reader.read();
             if (accumulator != null) accumulator.append((char)lastread);
             if (lastread != '\n' && lastread != '\r') col++;
-            if (lastread == '\n') { parserLine = ++line; col = 0; }
+            if (lastread == '\n') {
+                // col is -1 if we just unread a newline, this is sort of ugly
+                if (col != -1) parserLine = ++line;
+                col = 0;
+            }
             return lastread;
         }
 
index 670f68e..10159b7 100644 (file)
@@ -168,11 +168,11 @@ class Parser extends Lexer implements ByteCodes {
             if (peekToken() != RB)
                 while(true) {                                               // iterate over the initialization values
                     int size = b.size();
+                    b.add(parserLine, LITERAL, new Integer(i++));           // push the index in the array to place it into
                     if (peekToken() == COMMA || peekToken() == RB)
                         b.add(parserLine, LITERAL, null);                   // for stuff like [1,,2,]
                     else
                         startExpr(b, -1);                                   // push the value onto the stack
-                    b.add(parserLine, LITERAL, new Integer(i++));           // push the index in the array to place it into
                     b.add(parserLine, PUT);                                 // put it into the array
                     b.add(parserLine, POP);                                 // discard the value remaining on the stack
                     if (peekToken() == RB) break;