QoreValue QoreValueList::takeExists(ptrdiff_t offset) { QoreValue* ptr = getExistingEntryPtr(offset); if (!ptr) return QoreValue(); QoreValue rv = *ptr; *ptr = QoreValue(); return rv; }
QoreValue QoreShiftLeftEqualsOperatorNode::evalValueImpl(bool& needs_deref, ExceptionSink* xsink) const { int64 val = right->bigIntEval(xsink); if (*xsink) return QoreValue(); // get ptr to current value (lvalue is locked for the scope of the LValueHelper object) LValueHelper v(left, xsink); if (!v) return QoreValue(); return v.shiftLeftEqualsBigInt(val, "<<= operator>"); }
// evalImpl(): return value requires a deref(xsink) if not 0 QoreValue CallReferenceCallNode::evalValueImpl(bool& needs_deref, ExceptionSink* xsink) const { ReferenceHolder<AbstractQoreNode> lv(exp->eval(xsink), xsink); if (*xsink) return QoreValue(); ResolvedCallReferenceNode* r = dynamic_cast<ResolvedCallReferenceNode*>(*lv); if (!r) { xsink->raiseException("REFERENCE-CALL-ERROR", "expression does not evaluate to a call reference (evaluated to type '%s')", lv ? lv->getTypeName() : "NOTHING"); return QoreValue(); } return r->execValue(args, xsink); }
QoreValue QoreModulaOperatorNode::evalValueImpl(bool& needs_deref, ExceptionSink* xsink) const { int64 l = left->bigIntEval(xsink); if (*xsink) return QoreValue(); int64 r = right->bigIntEval(xsink); if (*xsink) return QoreValue(); if (!r) { xsink->raiseException("DIVISION-BY-ZERO", "modula operand cannot be zero ("QLLD" %% "QLLD" attempted)", l, r); return QoreValue(); } return l % r; }
QoreValue QoreValueList::minValue(ExceptionSink* xsink) const { if (!priv->length) return QoreValue(); QoreValue rv = priv->entry[0]; for (size_t i = 1; i < priv->length; ++i) { QoreValue v = priv->entry[i]; if (QoreLogicalLessThanOperatorNode::doLessThan(v, rv, xsink)) rv = v; if (*xsink) return QoreValue(); } return rv.refSelf(); }
QoreValue QoreValueList::pop() { assert(reference_count() == 1); if (!priv->length) return QoreValue(); QoreValue& rv = priv->entry[priv->length - 1]; size_t pos = priv->length - 1; priv->entry[pos] = QoreValue(); priv->resize(pos); if (rv.hasNode() && get_container_obj(rv.getInternalNode())) priv->incObjectCount(-1); return rv; }
QoreValue VarRefNewObjectNode::evalValueImpl(bool& needs_deref, ExceptionSink* xsink) const { assert(typeInfo->getUniqueReturnClass()); ReferenceHolder<QoreObject> obj(qore_class_private::execConstructor(*typeInfo->getUniqueReturnClass(), variant, args, xsink), xsink); if (*xsink) return QoreValue(); QoreObject* rv = *obj; LValueHelper lv(this, xsink); if (!lv) return QoreValue(); lv.assign(obj.release()); if (*xsink) return QoreValue(); return QoreValue(rv->refSelf()); }
QoreValue QorePreIncrementOperatorNode::evalValueImpl(bool& needs_deref, ExceptionSink* xsink) const { // get ptr to current value (lvalue is locked for the scope of the LValueHelper object) LValueHelper n(exp, xsink); if (!n) return QoreValue(); if (n.getType() == NT_NUMBER) { n.preIncrementNumber("<++ (pre) operator>"); assert(!*xsink); } else if (n.getType() == NT_FLOAT) return n.preIncrementFloat("<++ (pre) operator>"); else return n.preIncrementBigInt("<++ (pre) operator>"); return *xsink || !ref_rv ? QoreValue() : n.getReferencedValue(); }
// returns a RunTimeObjectMethodReference or NULL if there's an exception QoreValue ParseObjectMethodReferenceNode::evalValueImpl(bool& needs_deref, ExceptionSink* xsink) const { // evaluate lvalue expression ReferenceHolder<AbstractQoreNode> lv(exp->eval(xsink), xsink); if (*xsink) return QoreValue(); QoreObject* o = (*lv) && (*lv)->getType() == NT_OBJECT ? reinterpret_cast<QoreObject*>(*lv) : 0; if (!o) { xsink->raiseException("OBJECT-METHOD-REFERENCE-ERROR", "expression does not evaluate to an object"); return QoreValue(); } //printd(5, "ParseObjectMethodReferenceNode::evalImpl() this: %p o: %p %s::%s() m: %p\n", this, o, o->getClassName(), method.c_str(), m); const QoreClass* oc = o->getClass(); // find the method at runtime if necessary if (!m) { // serialize method resolution at runtime AutoLocker al(lck); // check m again inside the lock (this way we avoid the lock in the common case where the method has already been resolved) if (!m) { bool m_priv = false; m = oc->findMethod(method.c_str(), m_priv); if (!m) { m = oc->findStaticMethod(method.c_str(), m_priv); if (!m) { xsink->raiseException("OBJECT-METHOD-REFERENCE-ERROR", "cannot resolve reference to %s::%s(): unknown method", o->getClassName(), method.c_str()); return QoreValue(); } } if (m_priv && !qore_class_private::runtimeCheckPrivateClassAccess(*oc)) { if (m->isPrivate()) xsink->raiseException("ILLEGAL-CALL-REFERENCE", "cannot create a call reference to private %s::%s() from outside the class", o->getClassName(), method.c_str()); else xsink->raiseException("ILLEGAL-CALL-REFERENCE", "cannot create a call reference to %s::%s() because the parent class that implements the method (%s::%s()) is privately inherited", o->getClassName(), method.c_str(), m->getClass()->getName(), method.c_str()); return QoreValue(); } } } if (oc == m->getClass() || oc == qc) return new RunTimeResolvedMethodReferenceNode(o, m); return new RunTimeObjectMethodReferenceNode(o, method.c_str()); }
QoreValue QoreValueList::maxValue(const ResolvedCallReferenceNode* fr, ExceptionSink* xsink) const { if (!priv->length) return QoreValue(); QoreValue rv = priv->entry[0]; for (size_t i = 1; i < priv->length; ++i) { QoreValue v = priv->entry[i]; safe_qorelist_t args(do_args(v, rv), xsink); ValueHolder result(fr->execValue(*args, xsink), xsink); if (*xsink) return QoreValue(); if (result->getAsBigInt() > 0) rv = v; } return rv.refSelf(); }
QoreValue QoreProgram::getGlobalVariableVal(const char* var, bool& found) const { const qore_ns_private* vns = 0; Var* v = qore_root_ns_private::runtimeFindGlobalVar(*(priv->RootNS), var, vns); if (!v) { found = false; return QoreValue(); } found = true; return v->eval(); }
QoreValue QoreAssignmentOperatorNode::evalValueImpl(bool& needs_deref, ExceptionSink* xsink) const { /* assign new value, this value gets referenced with the eval(xsink) call, so there's no need to reference it again for the variable assignment - however it does need to be copied/referenced for the return value */ ValueEvalRefHolder new_value(right, xsink); if (*xsink) return QoreValue(); // get ptr to current value (lvalue is locked for the scope of the LValueHelper object) LValueHelper v(left, xsink); if (!v) return QoreValue(); // assign new value if (v.assign(new_value.takeReferencedValue())) return QoreValue(); // reference return value if necessary return ref_rv ? v.getReferencedValue() : QoreValue(); }
QoreValue QoreHashMapOperatorNode::mapIterator(AbstractIteratorHelper& h, ExceptionSink* xsink) const { ReferenceHolder<QoreHashNode> rv(ref_rv ? new QoreHashNode : 0, xsink); qore_size_t i = 0; // set offset in thread-local data for "$#" while (true) { bool has_next = h.next(xsink); if (*xsink) return QoreValue(); if (!has_next) break; ImplicitElementHelper eh(i++); ReferenceHolder<> iv(h.getValue(xsink), xsink); if (*xsink) return QoreValue(); // check if value can be mapped SingleArgvContextHelper argv_helper(*iv, xsink); { ValueEvalRefHolder ekey(e[0], xsink); if (*xsink) return QoreValue(); // we have to convert to a string in the default encoding to use a hash key QoreStringValueHelper key(*ekey, QCS_DEFAULT, xsink); if (*xsink) return QoreValue(); ValueEvalRefHolder val(e[1], xsink); if (*xsink) return QoreValue(); if (ref_rv) rv->setKeyValue(key->getBuffer(), val.getReferencedValue(), xsink); } // if there is an exception dereferencing one of the evaluted nodes above, then exit the loop if (*xsink) return QoreValue(); } return rv.release(); }
QoreValue QoreDotEvalOperatorNode::evalValueImpl(bool& needs_deref, ExceptionSink* xsink) const { ValueEvalRefHolder op(left, xsink); if (*xsink) return QoreValue(); if (op->getType() == NT_HASH) { const AbstractQoreNode* ref = check_call_ref(op->getInternalNode(), m->getName()); if (ref) return reinterpret_cast<const ResolvedCallReferenceNode*>(ref)->execValue(m->getArgs(), xsink); } if (op->getType() != NT_OBJECT) { // FIXME: inefficient ReferenceHolder<> nop(op.getReferencedValue(), xsink); if (m->isPseudo()) return m->execPseudo(*nop, xsink); return pseudo_classes_eval(*nop, m->getName(), m->getArgs(), xsink); } QoreObject* o = const_cast<QoreObject*>(reinterpret_cast<const QoreObject*>(op->getInternalNode())); // FIXME: inefficient return m->exec(o, xsink); }
QoreValue QoreDivideEqualsOperatorNode::evalValueImpl(bool& needs_deref, ExceptionSink* xsink) const { ValueEvalRefHolder res(right, xsink); if (*xsink) return QoreValue(); // get ptr to current value (lvalue is locked for the scope of the LValueHelper object) LValueHelper v(left, xsink); if (!v) return QoreValue(); // is either side a number? if (res->getType() == NT_NUMBER || v.getType() == NT_NUMBER) { // check for divide by zero if (res->getAsFloat() == 0.0) { xsink->raiseException("DIVISION-BY-ZERO", "division by zero in arbitrary-precision numeric expression"); return QoreValue(); } // FIXME: efficiency ReferenceHolder<> rh(res.getReferencedValue(), xsink); v.divideEqualsNumber(*rh, "</= operator>"); } // is either side a float? else if (res->getType() == NT_FLOAT || v.getType() == NT_FLOAT) { double val = res->getAsFloat(); if (val == 0.0) { xsink->raiseException("DIVISION-BY-ZERO", "division by zero in floating-point expression"); return QoreValue(); } return v.divideEqualsFloat(val, "</= operator>"); } else { // do integer divide equals int64 val = res->getAsBigInt(); if (!val) { xsink->raiseException("DIVISION-BY-ZERO", "division by zero in integer expression"); return QoreValue(); } // get new value if necessary return v.divideEqualsBigInt(val, "</= operator>"); } // reference return value and return return ref_rv ? v.getReferencedValue() : QoreValue(); }
QoreValue QoreValueList::retrieveEntry(size_t num) { if (num >= priv->length) return QoreValue(); return priv->entry[num]; }
QoreValue MethodCallReferenceNode::execValue(const QoreListNode* args, ExceptionSink* xsink) const { ProgramThreadCountContextHelper tch(xsink, pgm, true); if (*xsink) return QoreValue(); return qore_method_private::eval(*method, runtime_get_stack_object(), args, xsink); }
QoreValue QoreValueList::getReferencedEntry(size_t num) const { if (num >= priv->length) return QoreValue(); return priv->entry[num].refSelf(); }
QoreValue QoreHashMapOperatorNode::evalValueImpl(bool& needs_deref, ExceptionSink* xsink) const { ValueEvalRefHolder arg_lst(e[2], xsink); if (*xsink || arg_lst->isNothing()) return QoreValue(); qore_type_t arglst_type = arg_lst->getType(); assert(arglst_type != NT_NOTHING); ReferenceHolder<QoreHashNode> ret_val(ref_rv ? new QoreHashNode : 0, xsink); if (NT_LIST != arglst_type) { // Single value // check if it's an AbstractIterator object if (NT_OBJECT == arglst_type) { AbstractIteratorHelper h(xsink, "hmap operator select", const_cast<QoreObject*>(arg_lst->get<const QoreObject>())); if (*xsink) return QoreValue(); if (h) return mapIterator(h, xsink); // TODO!! // passed iterator } // check if value can be mapped ReferenceHolder<> arg_ival(arg_lst.getReferencedValue(), xsink); SingleArgvContextHelper argv_helper(*arg_ival, xsink); ValueEvalRefHolder arg_key(e[0], xsink); if (*xsink) return QoreValue(); ValueEvalRefHolder arg_val(e[1], xsink); if (*xsink) return QoreValue(); // we have to convert to a string in the default encoding to use a hash key QoreStringValueHelper str_util(*arg_key, QCS_DEFAULT, xsink); if (*xsink) return QoreValue(); // Insert key-Value pair to the hash ret_val->setKeyValue(str_util->getBuffer(), arg_val.getReferencedValue(), xsink); } else {// List of values ConstListIterator li(arg_lst->get<const QoreListNode>()); while (li.next()) { // set offset in thread-local data for "$#" ImplicitElementHelper eh(li.index()); SingleArgvContextHelper argv_helper(li.getValue(), xsink); { ValueEvalRefHolder ekey(e[0], xsink); if (*xsink) return QoreValue(); // we have to convert to a string in the default encoding to use a hash key QoreStringValueHelper key(*ekey, QCS_DEFAULT, xsink); if (*xsink) return QoreValue(); ValueEvalRefHolder val(e[1], xsink); if (*xsink) return QoreValue(); if (ref_rv) ret_val->setKeyValue(key->getBuffer(), val.getReferencedValue(), xsink); } // if there is an exception dereferencing one of the evaluted nodes above, then exit the loop if (*xsink) return QoreValue(); } } if (*xsink || !ref_rv) return QoreValue(); return ret_val.release(); }