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")) {
}
/** 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) {
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 {
}
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) {
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());
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");
}
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;
}
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");
}
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; }
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;
}
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;