static int evalFloatExpr(Ejs *ep, double l, int rel, double r);
#endif
static int evalBoolExpr(Ejs *ep, bool l, int rel, bool r);
+static int evalPtrExpr(Ejs *ep, void *l, int rel, void *r);
static int evalNumericExpr(Ejs *ep, MprNum l, int rel, MprNum r);
static int evalStringExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs);
static int evalFunction(Ejs *ep, MprVar *obj, int flags);
#if BLD_DEBUG
fullNameLen = mprReallocStrcat(&fullName, MPR_MAX_VAR, fullNameLen,
- 0, ".", 0);
+ 0, ".", NULL);
#endif
ep->currentProperty = vp;
* If not executing yet, id may not be known
*/
fullNameLen = mprReallocStrcat(&fullName, MPR_MAX_VAR,
- fullNameLen, 0, "[", id, "]", 0);
+ fullNameLen, 0, "[", id, "]", NULL);
}
#endif
*id = mprStrdup(ep->token);
#if BLD_DEBUG
*fullNameLen = mprReallocStrcat(fullName, MPR_MAX_VAR, *fullNameLen,
- 0, *id, 0);
+ 0, *id, NULL);
#endif
if (ep->currentObj == 0) {
ep->currentObj = ejsFindObj(ep, state, *id, flags);
return 0;
}
+
+/*
+ return true if this string is a valid number
+*/
+static int string_is_number(const char *s)
+{
+ char *endptr = NULL;
+ if (s == NULL || *s == 0) {
+ return 0;
+ }
+ strtod(s, &endptr);
+ if (endptr != NULL && *endptr == 0) {
+ return 1;
+ }
+ return 0;
+}
+
/******************************************************************************/
/*
* Evaluate an operation. Returns with the result in ep->result. Returns -1
/* Nothing more can be done */
}
+ /* undefined and null are special, in that they don't get promoted when
+ comparing */
+ if (rel == EJS_EXPR_EQ || rel == EJS_EXPR_NOTEQ) {
+ if (lhs->type == MPR_TYPE_UNDEFINED || rhs->type == MPR_TYPE_UNDEFINED) {
+ return evalBoolExpr(ep,
+ lhs->type == MPR_TYPE_UNDEFINED,
+ rel,
+ rhs->type == MPR_TYPE_UNDEFINED);
+ }
+
+ if (lhs->type == MPR_TYPE_NULL || rhs->type == MPR_TYPE_NULL) {
+ return evalBoolExpr(ep,
+ lhs->type == MPR_TYPE_NULL,
+ rel,
+ rhs->type == MPR_TYPE_NULL);
+ }
+ }
+
/*
* From here on, lhs and rhs may contain allocated data (strings), so
* we must always destroy before overwriting.
*/
if (lhs->type != rhs->type) {
if (lhs->type == MPR_TYPE_STRING) {
- if (isdigit((int) lhs->string[0])) {
+ if (string_is_number(lhs->string)) {
num = mprVarToNumber(lhs);
lhs->allocatedVar = 0;
mprDestroyVar(lhs);
case EJS_EXPR_NOTEQ:
lval = lhs->type != rhs->type;
break;
+ case EJS_EXPR_BOOL_COMP:
+ lval = ! mprVarToBool(rhs);
+ break;
default:
lval = 0;
}
return 0;
case MPR_TYPE_PTR:
- mprCopyVarValue(&ep->result, mprCreateBoolVar(lhs->ptr == rhs->ptr), 0);
- return 0;
+ rc = evalPtrExpr(ep, lhs->ptr, rel, rhs->ptr);
+ break;
case MPR_TYPE_BOOL:
rc = evalBoolExpr(ep, lhs->boolean, rel, rhs->boolean);
return 0;
}
+static int evalPtrExpr(Ejs *ep, void *l, int rel, void *r)
+{
+ bool lval;
+
+ switch (rel) {
+ case EJS_EXPR_EQ:
+ lval = l == r;
+ break;
+ case EJS_EXPR_NOTEQ:
+ lval = l != r;
+ break;
+ case EJS_EXPR_BOOL_COMP:
+ lval = (r == NULL) ? 1 : 0;
+ break;
+ default:
+ ejsError(ep, "Bad operator %d", rel);
+ return -1;
+ }
+ mprCopyVarValue(&ep->result, mprCreateBoolVar(lval), 0);
+ return 0;
+}
+
/******************************************************************************/
/*
* Expressions with numeric operands
case MPR_TYPE_STRING_CFUNCTION:
if (actualArgs->used > 0) {
- argBuf = mprMalloc(actualArgs->used * sizeof(char*));
+ argBuf = mprMalloc((1+actualArgs->used) * sizeof(char*));
for (i = 0; i < actualArgs->used; i++) {
mprVarToString(&argBuf[i], MPR_MAX_STRING, 0, argValues[i]);
}
+ argBuf[i] = NULL;
} else {
argBuf = 0;
}
formalArgs = prototype->function.args;
argNames = (char**) formalArgs->handles;
-#if FUTURE
- if (formalArgs->used != actualArgs->used) {
- ejsError(ep, "Bad number of args. Should be %d", formalArgs->used);
+ if (formalArgs->used > actualArgs->used) {
+ ejsError(ep, "Bad number of args. Should be %d",
+ formalArgs->used);
return -1;
}
-#endif
/*
* Create the arguments and callee variables