/* * Coerce operands for invokeOperator */ static EjsVar *coerceBooleanOperands(Ejs *ejs, EjsVar *lhs, int opcode, EjsVar *rhs) { switch (opcode) { case EJS_OP_ADD: if (ejsIsUndefined(rhs)) { return (EjsVar*) ejs->nanValue; } else if (ejsIsNull(rhs) || ejsIsNumber(rhs) || ejsIsDate(rhs)) { return ejsInvokeOperator(ejs, (EjsVar*) ejsToNumber(ejs, lhs), opcode, rhs); } else { return ejsInvokeOperator(ejs, (EjsVar*) ejsToString(ejs, lhs), opcode, rhs); } break; case EJS_OP_AND: case EJS_OP_DIV: case EJS_OP_MUL: case EJS_OP_OR: case EJS_OP_REM: case EJS_OP_SHL: case EJS_OP_SHR: case EJS_OP_SUB: case EJS_OP_USHR: case EJS_OP_XOR: return ejsInvokeOperator(ejs, (EjsVar*) ejsToNumber(ejs, lhs), opcode, rhs); case EJS_OP_COMPARE_LE: case EJS_OP_COMPARE_LT: case EJS_OP_COMPARE_GE: case EJS_OP_COMPARE_GT: case EJS_OP_COMPARE_EQ: case EJS_OP_COMPARE_NE: if (ejsIsString(rhs)) { return ejsInvokeOperator(ejs, (EjsVar*) ejsToString(ejs, lhs), opcode, rhs); } return ejsInvokeOperator(ejs, (EjsVar*) ejsToNumber(ejs, lhs), opcode, rhs); case EJS_OP_COMPARE_STRICTLY_NE: return (EjsVar*) ejs->trueValue; case EJS_OP_COMPARE_STRICTLY_EQ: return (EjsVar*) ejs->falseValue; /* * Unary operators */ case EJS_OP_LOGICAL_NOT: case EJS_OP_NOT: case EJS_OP_NEG: return 0; case EJS_OP_COMPARE_NOT_ZERO: case EJS_OP_COMPARE_TRUE: return (EjsVar*) (((EjsBoolean*) lhs)->value ? ejs->trueValue: ejs->falseValue); case EJS_OP_COMPARE_ZERO: case EJS_OP_COMPARE_FALSE: return (EjsVar*) (((EjsBoolean*) lhs)->value ? ejs->falseValue : ejs->trueValue); case EJS_OP_COMPARE_UNDEFINED: case EJS_OP_COMPARE_NULL: return (EjsVar*) ejs->falseValue; default: ejsThrowTypeError(ejs, "Opcode %d not valid for type %s", opcode, lhs->type->qname.name); return ejs->undefinedValue; } }
/* Cast operands as required for invokeArrayOperator */ static EjsObj *coerceArrayOperands(Ejs *ejs, EjsObj *lhs, int opcode, EjsObj *rhs) { switch (opcode) { /* Binary operators */ case EJS_OP_ADD: return ejsInvokeOperator(ejs, arrayToString(ejs, (EjsArray*) lhs, 0, 0), opcode, rhs); case EJS_OP_AND: case EJS_OP_DIV: case EJS_OP_MUL: case EJS_OP_OR: case EJS_OP_REM: case EJS_OP_SHL: case EJS_OP_SHR: case EJS_OP_SUB: case EJS_OP_USHR: case EJS_OP_XOR: return ejsInvokeOperator(ejs, ESV(zero), opcode, rhs); case EJS_OP_COMPARE_EQ: case EJS_OP_COMPARE_NE: if (!ejsIsDefined(ejs, rhs)) { return ((opcode == EJS_OP_COMPARE_EQ) ? ESV(false): ESV(true)); } else if (ejsIs(ejs, rhs, Number)) { return ejsInvokeOperator(ejs, ejsToNumber(ejs, lhs), opcode, rhs); } return ejsInvokeOperator(ejs, ejsToString(ejs, lhs), opcode, rhs); case EJS_OP_COMPARE_LE: case EJS_OP_COMPARE_LT: case EJS_OP_COMPARE_GE: case EJS_OP_COMPARE_GT: if (ejsIs(ejs, rhs, Number)) { return ejsInvokeOperator(ejs, ejsToNumber(ejs, lhs), opcode, rhs); } return ejsInvokeOperator(ejs, ejsToString(ejs, lhs), opcode, rhs); case EJS_OP_COMPARE_STRICTLY_NE: case EJS_OP_COMPARE_UNDEFINED: case EJS_OP_COMPARE_NOT_ZERO: case EJS_OP_COMPARE_NULL: return ESV(true); case EJS_OP_COMPARE_STRICTLY_EQ: case EJS_OP_COMPARE_FALSE: case EJS_OP_COMPARE_TRUE: case EJS_OP_COMPARE_ZERO: return ESV(false); /* Unary operators */ case EJS_OP_LOGICAL_NOT: case EJS_OP_NOT: case EJS_OP_NEG: return 0; default: ejsThrowTypeError(ejs, "Opcode %d not valid for type %@", opcode, TYPE(lhs)->qname.name); return ESV(undefined); } }
/* Set a byte in the file at the offset designated by slotNum. */ static int setFileProperty(Ejs *ejs, EjsFile *fp, int slotNum, EjsObj *value) { MprOff offset; int c; if (!(fp->mode & EJS_FILE_OPEN)) { ejsThrowIOError(ejs, "File is not open"); return 0; } if (!(fp->mode & EJS_FILE_WRITE)) { ejsThrowIOError(ejs, "File is not opened for writing"); return 0; } c = ejsIs(ejs, value, Number) ? ejsGetInt(ejs, value) : ejsGetInt(ejs, ejsToNumber(ejs, value)); offset = mprSeekFile(fp->file, SEEK_CUR, 0); if (slotNum < 0) { // could have an mprGetPosition(file) API slotNum = (int) offset; } #if ME_CC_MMU && FUTURE fp->mapped[slotNum] = c; #else if (offset != slotNum && mprSeekFile(fp->file, SEEK_SET, slotNum) != slotNum) { ejsThrowIOError(ejs, "Cannot seek to file offset"); return 0; } if (mprPutFileChar(fp->file, c) < 0) { ejsThrowIOError(ejs, "Cannot write file"); return 0; } #endif return slotNum; }
/* Cast the object operand to a primitive type */ static EjsObj *xlCast(Ejs *ejs, EjsXML *vp, EjsType *type) { MprBuf *buf; EjsObj *result; EjsXML *elt, *item; int next; if (type == ESV(XML)) { return (EjsObj*) vp; } switch (type->sid) { case S_Object: case S_Boolean: return (EjsObj*) ejsCreateBoolean(ejs, 1); case S_Number: result = xlCast(ejs, vp, ESV(String)); result = (EjsObj*) ejsToNumber(ejs, result); return result; case S_String: buf = mprCreateBuf(MPR_BUFSIZE, -1); if (mprGetListLength(vp->elements) == 1) { elt = mprGetFirstItem(vp->elements); if (elt->kind == EJS_XML_ELEMENT) { if (elt->elements == 0) { return (EjsObj*) ESV(empty); } if (elt->elements && mprGetListLength(elt->elements) == 1) { // TODO - what about PI and comments? item = mprGetFirstItem(elt->elements); if (item->kind == EJS_XML_TEXT) { return (EjsObj*) item->value; } } } } for (next = 0; (elt = mprGetNextItem(vp->elements, &next)) != 0; ) { if (ejsXMLToBuf(ejs, buf, elt, -1) < 0) { return 0; } if (next < vp->elements->length) { mprPutStringToBuf(buf, " "); } } return (EjsObj*) ejsCreateStringFromAsc(ejs, (char*) buf->start); default: ejsThrowTypeError(ejs, "Cannot cast to this type"); return 0; } }
/* Cast the object operand to a primitive type */ static EjsAny *castXml(Ejs *ejs, EjsXML *xml, EjsType *type) { EjsXML *item; EjsObj *result; MprBuf *buf; assert(ejsIsXML(ejs, xml)); if (type == ESV(XMLList)) { return xml; } switch (type->sid) { case S_Object: case S_Boolean: return ejsCreateBoolean(ejs, 1); case S_Number: result = castXml(ejs, xml, ESV(String)); return ejsToNumber(ejs, result); case S_String: if (xml->kind == EJS_XML_ELEMENT) { if (xml->elements == 0) { return ESV(empty); } if (xml->elements && mprGetListLength(xml->elements) == 1) { // TODO - what about PI and comments? item = mprGetFirstItem(xml->elements); if (item->kind == EJS_XML_TEXT) { return item->value; } } } buf = mprCreateBuf(BIT_MAX_BUFFER, -1); if (ejsXMLToBuf(ejs, buf, xml, -1) < 0) { return 0; } return ejsCreateStringFromAsc(ejs, (char*) buf->start); default: ejsThrowTypeError(ejs, "Cannot cast to this type"); return 0; } return 0; }
// TODO - rename static int ejsGetNumOption(Ejs *ejs, EjsObj *options, cchar *field, int defaultValue, bool optional) { EjsObj *vp; EjsNumber *num; vp = ejsGetPropertyByName(ejs, options, EN(field)); if (vp == 0) { if (optional) { return defaultValue; } ejsThrowArgError(ejs, "Required option \"%s\" is missing", field); return 0; } num = ejsToNumber(ejs, vp); if (!ejsIs(ejs, num, Number)) { ejsThrowArgError(ejs, "Bad option type for field \"%s\"", field); return 0; } return (int) num->value; }