Qore Programming Language 1.19.1
Loading...
Searching...
No Matches
QoreLValue.h
1/* -*- mode: c++; indent-tabs-mode: nil -*- */
2/*
3 QoreLValue.h
4
5 Qore Programming Language
6
7 Copyright (C) 2003 - 2023 Qore Technologies, s.r.o.
8
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the "Software"),
11 to deal in the Software without restriction, including without limitation
12 the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 and/or sell copies of the Software, and to permit persons to whom the
14 Software is furnished to do so, subject to the following conditions:
15
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 DEALINGS IN THE SOFTWARE.
26
27 Note that the Qore library is released under a choice of three open-source
28 licenses: MIT (as above), LGPL 2+, or GPL 2+; see README-LICENSE for more
29 information.
30*/
31
32#ifndef _QORE_INTERN_QORELVALUE_H
33
34#define _QORE_INTERN_QORELVALUE_H
35
36DLLLOCAL void check_lvalue_object_in_out(AbstractQoreNode* in, AbstractQoreNode* out);
37
38template <typename U = qore_value_u>
39class QoreLValue {
40protected:
41 // returns the old value just in case it needs to be dereferenced outside a lock
42 template <class T, typename t, int nt>
43 DLLLOCAL T* ensureUnique(AbstractQoreNode*& old) {
44 assert(type == QV_Node);
45 assert(assigned);
46 assert(!old);
47
48 if (!v.n)
49 return reinterpret_cast<T*>(v.n = new T);
50
51 if (v.n->getType() != nt) {
52 t i = T::getValue(v.n);
53 old = v.n;
54 return reinterpret_cast<T*>(v.n = new T(i));
55 }
56
57 if (v.n->is_unique())
58 return reinterpret_cast<T*>(v.n);
59
60 old = v.n;
61 return reinterpret_cast<T*>((v.n = old->realCopy()));
62 }
63
64 DLLLOCAL void reset() {
65 assert(!assigned || type != QV_Node || !v.n);
66 if (assigned) {
67 assigned = false;
68 assert(!static_assignment);
69 }
70 }
71
72public:
73 U v;
74 valtype_t type : 4;
75 bool fixed_type : 1;
76 bool assigned : 1;
77
78 // true if the assigned value was not referenced for the assignment
79 // and therefore should not be dereferenced
80 bool static_assignment : 1;
81
82 // true if assigned to a closure
83 bool is_closure : 1;
84
85 DLLLOCAL QoreLValue() : type(QV_Node), fixed_type(false), assigned(false), static_assignment(false),
86 is_closure(false) {
87#ifdef DEBUG
88 v.n = 0;
89#endif
90 reset();
91 }
92
93 DLLLOCAL QoreLValue(valtype_t t) : type(t), fixed_type(t != QV_Node), assigned(false), static_assignment(false),
94 is_closure(false) {
95#ifdef DEBUG
96 if (t == QV_Node)
97 v.n = 0;
98#endif
99 reset();
100 }
101
102 // fixed_type is assigned in set()
103 DLLLOCAL QoreLValue(const QoreTypeInfo* typeInfo) : assigned(false), static_assignment(false), is_closure(false) {
104#ifdef DEBUG
105 type = QV_Bool;
106#endif
107 set(typeInfo);
108 }
109
110 DLLLOCAL QoreLValue(const QoreLValue<U>& old) : type(old.type), fixed_type(old.fixed_type),
111 assigned(old.assigned), static_assignment(false), is_closure(old.is_closure) {
112 if (!assigned)
113 return;
114 switch (old.type) {
115 case QV_Bool: v.b = old.v.b; break;
116 case QV_Int: v.i = old.v.i; break;
117 case QV_Float: v.f = old.v.f; break;
118 case QV_Node:
119 v.n = old.v.n ? old.v.n->refSelf() : nullptr;
120 if (!is_closure)
121 check_lvalue_object_in_out(v.n, 0);
122 break;
123 default: assert(false);
124 // no break
125 }
126 }
127
128#ifdef DEBUG
129 DLLLOCAL ~QoreLValue() {
130 assert(!assigned || type != QV_Node || !v.n);
131 }
132#endif
133
134 DLLLOCAL void setClosure() {
135 assert(!is_closure);
136 is_closure = true;
137 }
138
139 DLLLOCAL valtype_t getOptimizedType() const {
140 return fixed_type ? type : QV_Node;
141 }
142
143 DLLLOCAL bool optimized() const {
144 return type != QV_Node && type != QV_Ref;
145 }
146
148
151 template<typename T>
152 DLLLOCAL typename detail::QoreValueCastHelper<T>::Result get() {
153 return assigned ? detail::QoreValueCastHelper<T>::cast(this, type) : nullptr;
154 }
155
157
160 template<typename T>
161 DLLLOCAL typename detail::QoreValueCastHelper<const T>::Result get() const {
162 return assigned ? detail::QoreValueCastHelper<const T>::cast(this, type) : nullptr;
163 }
164
165 DLLLOCAL const char* getFixedTypeName() const {
166 if (!fixed_type)
167 return "any";
168 switch (type) {
169 case QV_Int: return "int";
170 case QV_Float: return "float";
171 case QV_Bool: return "bool";
172 default:
173 assert(false);
174 }
175 }
176
177 DLLLOCAL bool isInt() {
178 if (!assigned) {
179 if (type != QV_Int) {
180 if (fixed_type)
181 return false;
182 type = QV_Int;
183 }
184 assigned = true;
185 v.i = 0;
186 return true;
187 }
188 if (type == QV_Int)
189 return true;
190 return false;
191 }
192
193 DLLLOCAL bool isFloat() {
194 if (!assigned) {
195 if (type != QV_Float) {
196 if (fixed_type)
197 return false;
198 type = QV_Float;
199 }
200 assigned = true;
201 v.f = 0.0;
202 return true;
203 }
204 if (type == QV_Float)
205 return true;
206 return false;
207 }
208
209 DLLLOCAL AbstractQoreNode* makeInt() {
210 assert(!fixed_type || type == QV_Int);
211 if (!assigned) {
212 assigned = true;
213 if (!type)
214 type = QV_Int;
215 v.i = 0;
216 return 0;
217 }
218 switch (type) {
219 case QV_Float: {
220 int64 i = (int64)v.f;
221 v.i = i;
222 type = QV_Int;
223 return 0;
224 }
225
226 case QV_Bool: {
227 int64 i = (int64)v.b;
228 v.i = i;
229 type = QV_Int;
230 return 0;
231 }
232
233 case QV_Node: {
234 int64 i = v.n ? v.n->getAsBigInt() : 0;
235 AbstractQoreNode* rv = v.n;
236 v.i = i;
237 type = QV_Int;
238 if (!is_closure)
239 check_lvalue_object_in_out(0, rv);
240 return rv;
241 }
242
243 case QV_Int:
244 break;
245
246 default:
247 assert(false);
248 }
249
250 return 0;
251 }
252
253 DLLLOCAL AbstractQoreNode* makeFloat() {
254 assert(!fixed_type || type == QV_Float);
255 if (!assigned) {
256 assigned = true;
257 if (!type)
258 type = QV_Float;
259 v.f = 0.0;
260 return 0;
261 }
262 switch (type) {
263 case QV_Int: {
264 double f = v.i;
265 v.f = f;
266 type = QV_Float;
267 return 0;
268 }
269
270 case QV_Bool: {
271 double f = v.b;
272 v.f = f;
273 type = QV_Float;
274 return 0;
275 }
276
277 case QV_Node: {
278 double f = v.n ? v.n->getAsFloat() : 0.0;
279 AbstractQoreNode* rv = v.n;
280 v.f = f;
281 type = QV_Float;
282 if (!is_closure)
283 check_lvalue_object_in_out(0, rv);
284 return rv;
285 }
286
287 case QV_Float:
288 break;
289
290 default:
291 assert(false);
292 }
293
294 return 0;
295 }
296
297 DLLLOCAL AbstractQoreNode* makeNumber() {
298 assert(!fixed_type);
299 if (!assigned) {
300 assigned = true;
301 if (!type)
302 type = QV_Node;
303 v.n = new QoreNumberNode;
304 return 0;
305 }
306 switch (type) {
307 case QV_Int: {
308 QoreNumberNode* n = new QoreNumberNode(v.i);
309 v.n = n;
310 type = QV_Node;
311 return 0;
312 }
313
314 case QV_Float: {
315 QoreNumberNode* n = new QoreNumberNode(v.f);
316 v.n = n;
317 type = QV_Node;
318 return 0;
319 }
320
321 case QV_Bool: {
322 QoreNumberNode* n = new QoreNumberNode((int64)v.b);
323 v.n = n;
324 type = QV_Node;
325 return 0;
326 }
327
328 case QV_Node: {
329 if (v.n && v.n->getType() == NT_NUMBER)
330 return 0;
331 QoreNumberNode* n = new QoreNumberNode(v.n);
332 AbstractQoreNode* rv = v.n;
333 v.n = n;
334 type = QV_Node;
335 if (!is_closure)
336 check_lvalue_object_in_out(0, rv);
337 return rv;
338 }
339
340 default:
341 assert(false);
342 }
343
344 return 0;
345 }
346
347 DLLLOCAL QoreValue takeValue() {
348 if (!assigned)
349 return QoreValue();
350
351 assigned = false;
352 assert(!static_assignment);
353
354 switch (type) {
355 case QV_Bool: return QoreValue(v.b);
356 case QV_Int: return QoreValue(v.i);
357 case QV_Float: return QoreValue(v.f);
358 case QV_Node:
359 if (!is_closure)
360 check_lvalue_object_in_out(0, v.n);
361 return QoreValue(v.n);
362 default: assert(false);
363 // no break
364 }
365 return false;
366 }
367
368 DLLLOCAL const QoreValue getValue() const {
369 if (!assigned)
370 return QoreValue();
371
372 switch (type) {
373 case QV_Bool: return QoreValue(v.b);
374 case QV_Int: return QoreValue(v.i);
375 case QV_Float: return QoreValue(v.f);
376 case QV_Node: return v.n;
377 default: assert(false);
378 // no break
379 }
380 return QoreValue();
381 }
382
383 DLLLOCAL QoreValue getValue() {
384 if (!assigned)
385 return QoreValue();
386
387 switch (type) {
388 case QV_Bool: return QoreValue(v.b);
389 case QV_Int: return QoreValue(v.i);
390 case QV_Float: return QoreValue(v.f);
391 case QV_Node: return v.n;
392 default: assert(false);
393 // no break
394 }
395 return QoreValue();
396 }
397
398 DLLLOCAL QoreValue getReferencedValue() const {
399 return getValue().refSelf();
400 }
401
402 DLLLOCAL bool needsScan() const {
403 if (!assigned || type != QV_Node || !v.n)
404 return false;
405
406 return needs_scan(v.n);
407 }
408
409 // never call when a lock is held
410 DLLLOCAL QoreValue getReferencedValue(bool& needs_deref) const {
411 if (!assigned) {
412 needs_deref = false;
413 return QoreValue();
414 }
415
416 if (type == QV_Node) {
417 needs_deref = false;
418 return QoreValue(v.n);
419 }
420
421 needs_deref = false;
422
423 switch (type) {
424 case QV_Bool: return QoreValue(v.b);
425 case QV_Int: return QoreValue(v.i);
426 case QV_Float: return QoreValue(v.f);
427 default: assert(false);
428 // no break
429 }
430 return QoreValue();
431 }
432
433 DLLLOCAL void discard(ExceptionSink* xsink) {
434 if (!assigned)
435 return;
436
437 if (type == QV_Node && v.n) {
438 if (!is_closure)
439 check_lvalue_object_in_out(0, v.n);
440 v.n->deref(xsink);
441 }
442 assigned = false;
443 }
444
445 DLLLOCAL bool hasValue() const {
446 if (!assigned)
447 return false;
448 switch (type) {
449 case QV_Bool: return v.b;
450 case QV_Int: return (bool)v.i;
451 case QV_Float: return (bool)v.f;
452 case QV_Node: return !is_nothing(v.n);
453 default: assert(false);
454 // no break
455 }
456 return false;
457 }
458
459 DLLLOCAL void set(const QoreTypeInfo* typeInfo) {
460 if (typeInfo == bigIntTypeInfo || typeInfo == softBigIntTypeInfo)
461 set(QV_Int);
462 else if (typeInfo == floatTypeInfo || typeInfo == softFloatTypeInfo)
463 set(QV_Float);
464 else if (typeInfo == boolTypeInfo || typeInfo == softBoolTypeInfo)
465 set(QV_Bool);
466 else
467 set(QV_Node);
468 }
469
470 DLLLOCAL void set(valtype_t t) {
471 assert(!assigned || type != QV_Node || !v.n);
472 type = t;
473 fixed_type = (t != QV_Node);
474#ifdef DEBUG
475 if (t == QV_Node)
476 v.n = 0;
477#endif
478 reset();
479 }
480
481 DLLLOCAL AbstractQoreNode* assign(bool b) {
482 if (fixed_type) {
483 if (!assigned)
484 assigned = true;
485 switch (type) {
486 case QV_Bool: v.b = false; return 0;
487 case QV_Int: v.i = (int64)b; return 0;
488 case QV_Float: v.f = (double)b; return 0;
489 default: assert(false);
490 // no break
491 }
492 }
493
495 if (assigned) {
496 if (type == QV_Node) {
497 if (!is_closure)
498 check_lvalue_object_in_out(0, v.n);
499 rv = v.n;
500 }
501 else
502 rv = 0;
503 }
504 else {
505 assigned = true;
506 rv = 0;
507 }
508
509 v.b = b;
510 type = QV_Bool;
511
512 return rv;
513 }
514
515 DLLLOCAL AbstractQoreNode* assign(int64 i) {
516 if (fixed_type) {
517 if (!assigned)
518 assigned = true;
519 switch (type) {
520 case QV_Bool: v.b = (bool)i; return 0;
521 case QV_Int: v.i = i; return 0;
522 case QV_Float: v.f = (double)i; return 0;
523 default: assert(false);
524 // no break
525 }
526 }
527
529 if (assigned) {
530 if (type == QV_Node) {
531 if (!is_closure)
532 check_lvalue_object_in_out(0, v.n);
533 rv = v.n;
534 }
535 else
536 rv = 0;
537 }
538 else {
539 assigned = true;
540 rv = 0;
541 }
542
543 v.i = i;
544 type = QV_Int;
545
546 return rv;
547 }
548
549 DLLLOCAL AbstractQoreNode* assign(double f) {
550 if (fixed_type) {
551 if (!assigned)
552 assigned = true;
553 switch (type) {
554 case QV_Bool: v.b = (bool)f; return 0;
555 case QV_Int: v.i = (int64)f; return 0;
556 case QV_Float: v.f = f; return 0;
557 default: assert(false);
558 // no break
559 }
560 }
561
563 if (assigned) {
564 if (type == QV_Node) {
565 if (!is_closure)
566 check_lvalue_object_in_out(0, v.n);
567 rv = v.n;
568 }
569 else
570 rv = 0;
571 }
572 else {
573 assigned = true;
574 rv = 0;
575 }
576
577 v.f = f;
578 type = QV_Float;
579
580 return rv;
581 }
582
584
587 DLLLOCAL void assignSetTakeInitial(QoreLValue<U>& n, QoreValue val) {
588 assert(!assigned);
589 assigned = true;
590 type = n.type;
591 if (n.static_assignment) {
592 static_assignment = n.static_assignment;
593 n.static_assignment = false;
594 }
595 switch (n.type) {
596 case QV_Bool:
597 v.b = n.v.b;
598 assert(val.getType() == NT_BOOLEAN);
599 n.v.b = val.v.b;
600 break;
601
602 case QV_Int:
603 v.i = n.v.i;
604 assert(val.getType() == NT_INT);
605 n.v.i = val.v.i;
606 break;
607
608 case QV_Float:
609 v.f = n.v.f;
610 assert(val.getType() == NT_FLOAT);
611 n.v.f = val.v.f;
612 break;
613
614 case QV_Node:
615 if (n.is_closure) {
616 assert(!is_closure);
617 is_closure = true;
618 }
619 v.n = n.v.n;
620 n.v.n = val.takeNode();
621 break;
622
623 default:
624 assert(false);
625 // no break
626 }
627 }
628
629 DLLLOCAL void assignSetTakeInitial(QoreLValue<U>& n) {
630 assert(!assigned);
631 if (!n.assigned)
632 return;
633 assigned = true;
634 type = n.type;
635 if (n.static_assignment) {
636 static_assignment = n.static_assignment;
637 n.static_assignment = false;
638 }
639 switch (n.type) {
640 case QV_Bool: v.b = n.v.b; n.v.b = false; break;
641 case QV_Int: v.i = n.v.i; n.v.i = 0; break;
642 case QV_Float: v.f = n.v.f; n.v.f = 0; break;
643 case QV_Node:
644 if (n.is_closure) {
645 assert(!is_closure);
646 is_closure = true;
647 }
648 v.n = n.v.n;
649 n.v.n = nullptr;
650 break;
651 default: assert(false);
652 // no break
653 }
654 n.assigned = false;
655 }
656
657 // note: destructive for "n"
658 // returns any AbstractQoreNode no longer needed (because it was converted to a base type)
659 DLLLOCAL AbstractQoreNode* assignAssumeInitial(QoreValue& n, bool is_static_assignment = false) {
660 assert(!assigned);
661 assert(!static_assignment);
662 //printd(5, "QoreLValue::assignAssumeInitial() this: %p n: %s sa: %d\n", this, n.getTypeName(), is_static_assignment);
663 if (is_static_assignment)
664 static_assignment = true;
665 return assignAssume(n);
666 }
667
668 DLLLOCAL void assignInitial(bool n) {
669 assert(!assigned);
670 assigned = true;
671 if (fixed_type) {
672 switch (type) {
673 case QV_Bool: v.b = n; return;
674 case QV_Int: v.i = (int64)n; return;
675 case QV_Float: v.f = (double)n; return;
676 default: assert(false);
677 // no break
678 }
679 }
680 type = QV_Bool;
681 v.b = n;
682 }
683
684 DLLLOCAL void assignInitial(int64 n) {
685 assert(!assigned);
686 assigned = true;
687 if (fixed_type) {
688 switch (type) {
689 case QV_Bool: v.b = (bool)n; return;
690 case QV_Int: v.i = n; return;
691 case QV_Float: v.f = (double)n; return;
692 default: assert(false);
693 // no break
694 }
695 }
696 type = QV_Int;
697 v.i = n;
698 }
699
700 DLLLOCAL void assignInitial(double n) {
701 assert(!assigned);
702 assigned = true;
703 if (fixed_type) {
704 switch (type) {
705 case QV_Bool: v.b = (bool)n; return;
706 case QV_Int: v.i = (int64)n; return;
707 case QV_Float: v.f = n; return;
708 default: assert(false);
709 // no break
710 }
711 }
712 type = QV_Float;
713 v.f = n;
714 }
715
716 DLLLOCAL AbstractQoreNode* assignInitial(AbstractQoreNode* n) {
717 assert(!assigned);
718 assigned = true;
719 if (fixed_type) {
720 switch (type) {
721 case QV_Bool:
722 v.b = n ? n->getAsBool() : false; return n;
723 case QV_Int: v.i = n ? n->getAsBigInt() : 0; return n;
724 case QV_Float: v.f = n ? n->getAsFloat() : 0; return n;
725 default: assert(false);
726 // no break
727 }
728 }
729 type = QV_Node;
730 v.n = n;
731 if (!is_closure)
732 check_lvalue_object_in_out(v.n, 0);
733 return 0;
734 }
735
736 DLLLOCAL AbstractQoreNode* assignInitial(QoreValue n) {
737 assert(!assigned);
738 return assignAssume(n);
739 }
740
741 // NOTE: destructive for "val":
742 DLLLOCAL AbstractQoreNode* assignAssume(QoreValue& val) {
743 if (fixed_type) {
744 if (!assigned)
745 assigned = true;
746 switch (type) {
747 case QV_Bool: v.b = val.getAsBool(); break;
748 case QV_Int: v.i = val.getAsBigInt(); break;
749 case QV_Float: v.f = val.getAsFloat(); break;
750 default: assert(false);
751 // no break
752 }
753 return val.takeIfNode();
754 }
755
757 if (assigned) {
758 if (type == QV_Node) {
759 if (!is_closure)
760 check_lvalue_object_in_out(0, v.n);
761 rv = v.n;
762 }
763 else
764 rv = nullptr;
765 }
766 else {
767 assigned = true;
768 rv = nullptr;
769 }
770
771 switch (val.type) {
772 case QV_Bool: v.b = val.v.b; if (type != QV_Bool) type = QV_Bool; break;
773 case QV_Int: v.i = val.v.i; if (type != QV_Int) type = QV_Int; break;
774 case QV_Float: v.f = val.v.f; if (type != QV_Float) type = QV_Float; break;
775 case QV_Node:
776 v.n = val.takeNode();
777 if (type != QV_Node)
778 type = QV_Node;
779 if (!is_closure)
780 check_lvalue_object_in_out(v.n, 0);
781 break;
782 default: assert(false);
783 // no break
784 }
785
786 return rv;
787 }
788
789 // the node is already referenced for the assignment
790 DLLLOCAL AbstractQoreNode* assign(AbstractQoreNode* n) {
791 if (fixed_type) {
792 if (!assigned)
793 assigned = true;
794
795 switch (type) {
796 case QV_Bool: {
797 if (n) {
798 v.b = n->getAsBool();
799 return n;
800 }
801 v.b = false;
802 return 0;
803 }
804 case QV_Int: {
805 if (n) {
806 v.i = n->getAsBigInt();
807 return n;
808 }
809 v.i = 0;
810 return 0;
811 }
812 case QV_Float: {
813 if (n) {
814 v.f = n->getAsFloat();
815 return n;
816 }
817 v.f = 0.0;
818 return 0;
819 }
820 case QV_Node: {
821 if (!is_closure)
822 check_lvalue_object_in_out(n, v.n);
823 AbstractQoreNode* rv = v.n;
824 v.n = n;
825 return rv;
826 }
827 default:
828 assert(false);
829 // no break
830 }
831 return 0;
832 }
833
835 if (assigned) {
836 if (type == QV_Node) {
837 if (!is_closure)
838 check_lvalue_object_in_out(0, v.n);
839 rv = v.n;
840 }
841 else
842 rv = 0;
843 }
844 else {
845 assigned = true;
846 rv = 0;
847 }
848
849 v.n = n;
850 if (!is_closure)
851 check_lvalue_object_in_out(v.n, 0);
852 if (type != QV_Node)
853 type = QV_Node;
854
855 return rv;
856 }
857
858 DLLLOCAL bool exists() const {
859 return assigned && (type != QV_Node || !is_nothing(v.n));
860 }
861
862 DLLLOCAL bool getAsBool() const {
863 if (assigned) {
864 switch (type) {
865 case QV_Bool: return v.b;
866 case QV_Int: return (bool)v.i;
867 case QV_Float: return (bool)v.f;
868 case QV_Node: return v.n ? v.n->getAsBool() : false;
869 default: assert(false);
870 // no break
871 }
872 }
873 return false;
874 }
875
876 DLLLOCAL int64 getAsBigInt() const {
877 if (assigned) {
878 switch (type) {
879 case QV_Bool: return (int64)v.b;
880 case QV_Int: return v.i;
881 case QV_Float: return (int64)v.f;
882 case QV_Node: return v.n ? v.n->getAsBigInt() : 0;
883 default: assert(false);
884 // no break
885 }
886 }
887 return 0;
888 }
889
890 DLLLOCAL double getAsFloat() const {
891 if (assigned) {
892 switch (type) {
893 case QV_Bool: return (double)v.b;
894 case QV_Int: return (double)v.i;
895 case QV_Float: return v.f;
896 case QV_Node: return v.n ? v.n->getAsFloat() : 0.0;
897 default: assert(false);
898 // no break
899 }
900 }
901 return 0.0;
902 }
903
904 DLLLOCAL AbstractQoreNode* getInternalNode() const {
905 return assigned && type == QV_Node ? v.n : nullptr;
906 }
907
908 DLLLOCAL qore_type_t getType() const {
909 if (assigned)
910 switch (type) {
911 case QV_Bool: return NT_BOOLEAN;
912 case QV_Int: return NT_INT;
913 case QV_Float: return NT_FLOAT;
914 case QV_Node: return v.n ? v.n->getType() : NT_NOTHING;
915 default: assert(false);
916 // no break
917 }
918 return NT_NOTHING;
919 }
920
921 DLLLOCAL const char* getTypeName() const {
922 if (assigned)
923 switch (type) {
924 case QV_Bool: return qoreBoolTypeName;
925 case QV_Int: return qoreIntTypeName;
926 case QV_Float: return qoreFloatTypeName;
927 case QV_Node: return get_type_name(v.n);
928 default: assert(false);
929 // no break
930 }
931 return "NOTHING";
932 }
933
934 // lvalue operations
935 DLLLOCAL int64 plusEqualsBigInt(int64 i, AbstractQoreNode*& old) {
936 assert(type == QV_Int);
937
938 switch (type) {
939 case QV_Int:
940 if (!assigned) {
941 assigned = true;
942 return v.i = i;
943 }
944 return v.i += i;
945
946 // to avoid warnings about missing enum values
947 default:
948 assert(false);
949 // no break
950 }
951
952 return 0;
953 }
954
955 DLLLOCAL double plusEqualsFloat(double f, AbstractQoreNode*& old) {
956 assert(type == QV_Float);
957
958 switch (type) {
959 case QV_Float:
960 if (!assigned) {
961 assigned = true;
962 return v.f = f;
963 }
964 return v.f += f;
965
966 // to avoid warnings about missing enum values
967 default:
968 assert(false);
969 // no break
970 }
971
972 return 0.0;
973 }
974
975 DLLLOCAL int64 minusEqualsBigInt(int64 i, AbstractQoreNode*& old) {
976 assert(type == QV_Int);
977
978 switch (type) {
979 case QV_Int:
980 if (!assigned) {
981 assigned = true;
982 return v.i = -i;
983 }
984 return v.i -= i;
985
986 // to avoid warnings about missing enum values
987 default:
988 assert(false);
989 // no break
990 }
991
992 return 0;
993 }
994
995 DLLLOCAL double minusEqualsFloat(double f, AbstractQoreNode*& old) {
996 assert(type == QV_Float);
997
998 switch (type) {
999 case QV_Float:
1000 if (!assigned) {
1001 assigned = true;
1002 return v.f = -f;
1003 }
1004 return v.f -= f;
1005
1006 // to avoid warnings about missing enum values
1007 default:
1008 assert(false);
1009 // no break
1010 }
1011
1012 return 0.0;
1013 }
1014
1015 DLLLOCAL int64 orEqualsBigInt(int64 i, AbstractQoreNode*& old) {
1016 assert(type == QV_Int);
1017
1018 switch (type) {
1019 case QV_Int:
1020 if (!assigned) {
1021 assigned = true;
1022 return v.i = i;
1023 }
1024 return v.i |= i;
1025
1026 // to avoid warnings about missing enum values
1027 default:
1028 assert(false);
1029 // no break
1030 }
1031
1032 return 0;
1033 }
1034
1035 DLLLOCAL int64 andEqualsBigInt(int64 i, AbstractQoreNode*& old) {
1036 assert(type == QV_Int);
1037
1038 switch (type) {
1039 case QV_Int:
1040 if (!assigned) {
1041 assigned = true;
1042 return v.i = 0;
1043 }
1044 return v.i &= i;
1045
1046 // to avoid warnings about missing enum values
1047 default:
1048 assert(false);
1049 // no break
1050 }
1051
1052 return 0;
1053 }
1054
1055 DLLLOCAL int64 modulaEqualsBigInt(int64 i, AbstractQoreNode*& old) {
1056 assert(type == QV_Int);
1057
1058 switch (type) {
1059 case QV_Int:
1060 if (!assigned) {
1061 assigned = true;
1062 return v.i = 0;
1063 }
1064 return i ? v.i %= i : v.i = 0;
1065
1066 // to avoid warnings about missing enum values
1067 default:
1068 assert(false);
1069 // no break
1070 }
1071
1072 return 0;
1073 }
1074
1075 DLLLOCAL int64 multiplyEqualsBigInt(int64 i, AbstractQoreNode*& old) {
1076 assert(type == QV_Int);
1077
1078 switch (type) {
1079 case QV_Int:
1080 if (!assigned) {
1081 assigned = true;
1082 return v.i = 0;
1083 }
1084 return v.i *= i;
1085
1086 // to avoid warnings about missing enum values
1087 default:
1088 assert(false);
1089 // no break
1090 }
1091
1092 return 0;
1093 }
1094
1095 DLLLOCAL int64 divideEqualsBigInt(int64 i, AbstractQoreNode*& old) {
1096 assert(type == QV_Int);
1097 assert(i);
1098
1099 switch (type) {
1100 case QV_Int:
1101 if (!assigned) {
1102 assigned = true;
1103 return v.i = 0;
1104 }
1105 return v.i /= i;
1106
1107 // to avoid warnings about missing enum values
1108 default:
1109 assert(false);
1110 // no break
1111 }
1112
1113 return 0;
1114 }
1115
1116 DLLLOCAL int64 xorEqualsBigInt(int64 i, AbstractQoreNode*& old) {
1117 assert(type == QV_Int);
1118
1119 switch (type) {
1120 case QV_Int:
1121 if (!assigned) {
1122 assigned = true;
1123 return v.i = i;
1124 }
1125 return v.i ^= i;
1126
1127 // to avoid warnings about missing enum values
1128 default:
1129 assert(false);
1130 // no break
1131 }
1132
1133 return 0;
1134 }
1135
1136 DLLLOCAL int64 shiftLeftEqualsBigInt(int64 i, AbstractQoreNode*& old) {
1137 assert(type == QV_Int);
1138
1139 switch (type) {
1140 case QV_Int:
1141 if (!assigned) {
1142 assigned = true;
1143 return v.i = 0;
1144 }
1145 return v.i <<= i;
1146
1147 // to avoid warnings about missing enum values
1148 default:
1149 assert(false);
1150 // no break
1151 }
1152
1153 return 0;
1154 }
1155
1156 DLLLOCAL int64 shiftRightEqualsBigInt(int64 i, AbstractQoreNode*& old) {
1157 assert(type == QV_Int);
1158
1159 switch (type) {
1160 case QV_Int:
1161 if (!assigned) {
1162 assigned = true;
1163 return v.i = 0;
1164 }
1165 return v.i >>= i;
1166
1167 // to avoid warnings about missing enum values
1168 default:
1169 assert(false);
1170 // no break
1171 }
1172
1173 return 0;
1174 }
1175
1176 DLLLOCAL int64 postIncrementBigInt(AbstractQoreNode*& old) {
1177 assert(type == QV_Int);
1178
1179 switch (type) {
1180 case QV_Int: {
1181 if (!assigned) {
1182 assigned = true;
1183 v.i = 1;
1184 return 0;
1185 }
1186 int64 rv = (int64)v.i;
1187 ++v.i;
1188 return rv;
1189 }
1190
1191 // to avoid warnings about missing enum values
1192 default:
1193 assert(false);
1194 // no break
1195 }
1196
1197 return 0;
1198 }
1199
1200 DLLLOCAL int64 preIncrementBigInt(AbstractQoreNode*& old) {
1201 assert(type == QV_Int);
1202
1203 switch (type) {
1204 case QV_Int:
1205 if (!assigned) {
1206 assigned = true;
1207 return v.i = 1;
1208 }
1209 return ++v.i;
1210
1211 // to avoid warnings about missing enum values
1212 default:
1213 assert(false);
1214 // no break
1215 }
1216
1217 return 0;
1218 }
1219
1220 DLLLOCAL int64 postDecrementBigInt(AbstractQoreNode*& old) {
1221 assert(type == QV_Int);
1222
1223 switch (type) {
1224 case QV_Int:
1225 if (!assigned) {
1226 assigned = true;
1227 v.i = -1;
1228 return 0;
1229 }
1230 return v.i--;
1231
1232 // to avoid warnings about missing enum values
1233 default:
1234 assert(false);
1235 // no break
1236 }
1237
1238 return 0;
1239 }
1240
1241 DLLLOCAL int64 preDecrementBigInt(AbstractQoreNode*& old) {
1242 assert(type == QV_Int);
1243
1244 switch (type) {
1245 case QV_Int:
1246 if (!assigned) {
1247 assigned = true;
1248 return v.i = -1;
1249 }
1250 return --v.i;
1251
1252 // to avoid warnings about missing enum values
1253 default:
1254 assert(false);
1255 // no break
1256 }
1257 return 0;
1258 }
1259
1260 DLLLOCAL double postIncrementFloat(AbstractQoreNode*& old) {
1261 assert(type == QV_Float);
1262
1263 switch (type) {
1264 case QV_Float:
1265 if (!assigned) {
1266 assigned = true;
1267 v.f = 1.0;
1268 return 0.0;
1269 }
1270 return v.f++;
1271
1272 // to avoid warnings about missing enum values
1273 default:
1274 assert(false);
1275 // no break
1276 }
1277
1278 return 0.0;
1279 }
1280
1281 DLLLOCAL double preIncrementFloat(AbstractQoreNode*& old) {
1282 assert(type == QV_Float);
1283
1284 switch (type) {
1285 case QV_Float:
1286 if (!assigned) {
1287 assigned = true;
1288 return v.f = 1.0;
1289 }
1290 return ++v.f;
1291
1292 // to avoid warnings about missing enum values
1293 default:
1294 assert(false);
1295 // no break
1296 }
1297
1298 return 0.0;
1299 }
1300
1301 DLLLOCAL double postDecrementFloat(AbstractQoreNode*& old) {
1302 assert(type == QV_Float);
1303
1304 switch (type) {
1305 case QV_Float:
1306 if (!assigned) {
1307 assigned = true;
1308 v.f = -1.0;
1309 return 0.0;
1310 }
1311 return v.f--;
1312
1313 // to avoid warnings about missing enum values
1314 default:
1315 assert(false);
1316 // no break
1317 }
1318
1319 return 0.0;
1320 }
1321
1322 DLLLOCAL double preDecrementFloat(AbstractQoreNode*& old) {
1323 assert(type == QV_Float);
1324
1325 switch (type) {
1326 case QV_Float:
1327 if (!assigned) {
1328 assigned = true;
1329 return v.f = -1.0;
1330 }
1331 return --v.f;
1332
1333 // to avoid warnings about missing enum values
1334 default:
1335 assert(false);
1336 // no break
1337 }
1338 return 0;
1339 }
1340
1341 DLLLOCAL double multiplyEqualsFloat(double f, AbstractQoreNode*& old) {
1342 assert(type == QV_Float);
1343
1344 switch (type) {
1345 case QV_Float:
1346 if (!assigned) {
1347 assigned = true;
1348 return v.f = 0;
1349 }
1350 return v.f *= f;
1351
1352 // to avoid warnings about missing enum values
1353 default:
1354 assert(false);
1355 // no break
1356 }
1357
1358 return 0;
1359 }
1360
1361 DLLLOCAL double divideEqualsFloat(double f, AbstractQoreNode*& old) {
1362 assert(type == QV_Float);
1363 assert(f);
1364
1365 switch (type) {
1366 case QV_Float:
1367 if (!assigned) {
1368 assigned = true;
1369 return v.f = 0;
1370 }
1371 return v.f /= f;
1372
1373 // to avoid warnings about missing enum values
1374 default:
1375 assert(false);
1376 // no break
1377 }
1378
1379 return 0;
1380 }
1381
1382 DLLLOCAL QoreValue remove(bool& was_static_assignment) {
1383 assert(!was_static_assignment);
1384
1385 if (!assigned)
1386 return QoreValue();
1387 assigned = false;
1388 if (static_assignment) {
1389 static_assignment = false;
1390 was_static_assignment = true;
1391 }
1392
1393 switch (type) {
1394 case QV_Bool:
1395 return v.b;
1396 case QV_Int:
1397 return v.i;
1398 case QV_Float:
1399 return v.f;
1400 case QV_Node:
1401 if (!is_closure)
1402 check_lvalue_object_in_out(0, v.n);
1403 return v.n;
1404 default:
1405 assert(false);
1406 // no break
1407 }
1408 return QoreValue();
1409 }
1410
1411 // ignore any current value and sets the lvalue to unassigned
1412 DLLLOCAL void unassignIgnore() {
1413 if (assigned) {
1414 assigned = false;
1415 if (static_assignment)
1416 static_assignment = false;
1417 if (type == QV_Node && !is_closure)
1418 check_lvalue_object_in_out(0, v.n);
1419 }
1420 }
1421
1422 DLLLOCAL QoreValue removeValue(bool for_del) {
1423 if (!assigned)
1424 return QoreValue();
1425 assigned = false;
1426 assert(!static_assignment);
1427
1428 switch (type) {
1429 case QV_Bool:
1430 return for_del ? QoreValue() : QoreValue(v.b);
1431 case QV_Int:
1432 return for_del ? QoreValue() : QoreValue(v.i);
1433 case QV_Float:
1434 return for_del ? QoreValue() : QoreValue(v.f);
1435 case QV_Node:
1436 if (!is_closure)
1437 check_lvalue_object_in_out(0, v.n);
1438 return v.n;
1439 default:
1440 assert(false);
1441 // no break
1442 }
1443 return QoreValue();
1444 }
1445};
1446
1447typedef QoreLValue<> QoreLValueGeneric;
1448
1449#endif
static bool is_nothing(const AbstractQoreNode *n)
to check if an AbstractQoreNode object is NOTHING
Definition: QoreLib.h:319
The base class for all value and parse types in Qore expression trees.
Definition: AbstractQoreNode.h:57
DLLEXPORT int64 getAsBigInt() const
returns the 64-bit integer value of the object
DLLEXPORT double getAsFloat() const
returns the float value of the object
virtual DLLEXPORT AbstractQoreNode * realCopy() const =0
returns a copy of the object; the caller owns the reference count
DLLEXPORT bool getAsBool() const
returns the boolean value of the object
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:50
Qore's arbitrary-precision number value type, dynamically-allocated only, reference counted.
Definition: QoreNumberNode.h:51
valtype_t type
indicates the value that the union is holding
Definition: QoreValue.h:118
qore_value_u v
the actual value is stored here
Definition: QoreValue.h:116
DLLEXPORT double getAsFloat() const
returns the value as a float
DLLEXPORT qore_type_t getType() const
returns the type of value contained
DLLEXPORT bool getAsBool() const
returns the value as a bool
DLLEXPORT int64 getAsBigInt() const
returns the value as an int
DLLEXPORT AbstractQoreNode * takeNode()
returns a referenced AbstractQoreNode pointer leaving "this" empty (value is taken from "this"); the ...
int16_t qore_type_t
used to identify unique Qore data and parse types (descendents of AbstractQoreNode)
Definition: common.h:70
long long int64
64bit integer type, cannot use int64_t here since it breaks the API on some 64-bit systems due to equ...
Definition: common.h:260
#define QV_Node
for heap-allocated values
Definition: QoreValue.h:46
#define QV_Ref
for references (when used with lvalues)
Definition: QoreValue.h:47
#define QV_Bool
for boolean values
Definition: QoreValue.h:43
#define QV_Float
for floating-point values
Definition: QoreValue.h:45
#define QV_Int
for integer values
Definition: QoreValue.h:44
const qore_type_t NT_BOOLEAN
type value for bools (QoreValue only)
Definition: node_types.h:47
const qore_type_t NT_NUMBER
type value for QoreNumberNode
Definition: node_types.h:53
const qore_type_t NT_INT
type value for integers (QoreValue only)
Definition: node_types.h:43
const qore_type_t NT_FLOAT
type value for floating-point values (QoreValue only)
Definition: node_types.h:44
const qore_type_t NT_NOTHING
type value for QoreNothingNode
Definition: node_types.h:42
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:276
DLLEXPORT AbstractQoreNode * takeIfNode()
returns a referenced value; leaving the "this" untouched; the caller owns the reference returned
DLLEXPORT QoreValue refSelf() const
references the contained value if type == QV_Node, returns itself
used in QoreValue::get()
Definition: QoreValue.h:67
bool b
for boolean values
Definition: QoreValue.h:57
double f
for double values
Definition: QoreValue.h:59
int64 i
for integer values
Definition: QoreValue.h:58