Formula.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #ifndef _Formula_h_
  2. #define _Formula_h_
  3. /* Formula.h
  4. *
  5. * Copyright (C) 1990-2011,2013,2014,2015,2016,2017 Paul Boersma
  6. *
  7. * This code is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or (at
  10. * your option) any later version.
  11. *
  12. * This code is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  15. * See the GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this work. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include "Data.h"
  21. #include <new>
  22. #define kFormula_EXPRESSION_TYPE_NUMERIC 0
  23. #define kFormula_EXPRESSION_TYPE_STRING 1
  24. #define kFormula_EXPRESSION_TYPE_NUMERIC_VECTOR 2
  25. #define kFormula_EXPRESSION_TYPE_NUMERIC_MATRIX 3
  26. #define kFormula_EXPRESSION_TYPE_NUMERIC_TENSOR3 4
  27. #define kFormula_EXPRESSION_TYPE_NUMERIC_TENSOR4 5
  28. #define kFormula_EXPRESSION_TYPE_STRING_ARRAY 6
  29. #define kFormula_EXPRESSION_TYPE_UNKNOWN 7
  30. Thing_declare (InterpreterVariable);
  31. typedef struct structStackel {
  32. #define Stackel_NUMBER 0
  33. #define Stackel_STRING 1
  34. #define Stackel_NUMERIC_VECTOR 2
  35. #define Stackel_NUMERIC_MATRIX 3
  36. #define Stackel_NUMERIC_TENSOR3 4
  37. #define Stackel_NUMERIC_TENSOR4 5
  38. #define Stackel_STRING_ARRAY 6
  39. #define Stackel_VARIABLE -1
  40. #define Stackel_OBJECT -2
  41. int which; // 0 or negative = no clean-up required, positive = requires clean-up
  42. bool owned; // relevant only to numeric vector/matrix/tensor3/tensor4
  43. /*
  44. The following member of structStackel can either be a struct or a union.
  45. The struct option is the easy option: no special care will have to be taken when assigning to its members.
  46. The union option attempts to optimize for space and perhaps speed by putting the variants into a smaller space,
  47. but it requires special logic for initialization, deletion, and assignment.
  48. The special logic is partly implemented by encapsulating _string as a "private" member.
  49. */
  50. #define STACKEL_VARIANTS_ARE_PACKED_IN_A_UNION 1
  51. #if STACKEL_VARIANTS_ARE_PACKED_IN_A_UNION
  52. union
  53. #else
  54. struct
  55. #endif
  56. {
  57. double number;
  58. autostring32 _string;
  59. Daata object;
  60. VEC numericVector;
  61. MAT numericMatrix;
  62. InterpreterVariable variable;
  63. };
  64. structStackel () {
  65. memset (this, 0, sizeof (structStackel)); // union-safe zeroing of all members of structStackel
  66. Melder_assert (our which == Stackel_NUMBER); // check that on this computer, 0 is represented with zero bits only
  67. Melder_assert (our number == 0.0); // check that on this computer, 0.0 is represented with zero bits only
  68. Melder_assert (! our _string); // check that on this computer, a plain-old-data null pointer is represented with zero bits only
  69. Melder_assert (! our object); // check that on this computer, a class null pointer is represented with zero bits only
  70. Melder_assert (! our owned); // check that on this computer, false is represented with zero bits only
  71. }
  72. void reset () { // union-safe destruction: test which variant we have
  73. if (our which <= Stackel_NUMBER)
  74. return;
  75. if (our which == Stackel_STRING) {
  76. our _string. reset();
  77. } else if (our which == Stackel_NUMERIC_VECTOR) {
  78. if (our owned) {
  79. {// scope
  80. autoVEC removable;
  81. removable. adoptFromAmbiguousOwner (our numericVector);
  82. }
  83. our numericVector = VEC (); // undangle
  84. }
  85. } else if (our which == Stackel_NUMERIC_MATRIX) {
  86. if (our owned) {
  87. {// scope
  88. autoMAT removable;
  89. removable. adoptFromAmbiguousOwner (our numericMatrix);
  90. }
  91. our numericMatrix = MAT (); // undangle
  92. }
  93. }
  94. }
  95. ~structStackel () { // union-safe destruction: test which variant we have
  96. our reset();
  97. }
  98. structStackel& operator= (structStackel&& other) noexcept { // generalized move assignment
  99. if (& other != this) {
  100. our reset();
  101. memmove (this, & other, sizeof (structStackel)); // union-safe: even our biggest variant is bit-copied entirely
  102. memset (& other, 0, sizeof (structStackel)); // union-safe: even the biggest variant in `other` is erased
  103. }
  104. return *this;
  105. }
  106. conststring32 getString () {
  107. return our _string.get();
  108. }
  109. autostring32 moveString () {
  110. return our _string.move();
  111. }
  112. void setString (autostring32 newString) {
  113. our reset();
  114. #if STACKEL_VARIANTS_ARE_PACKED_IN_A_UNION
  115. ::new (& our _string) autostring32(); // a convoluted and type-unsafe, but portable, way to null those 32 or 64 bits
  116. #endif
  117. our which = Stackel_STRING;
  118. our _string = newString.move();
  119. }
  120. conststring32 whichText ();
  121. } *Stackel;
  122. struct Formula_Result {
  123. int expressionType;
  124. double numericResult;
  125. autostring32 stringResult;
  126. VEC numericVectorResult;
  127. MAT numericMatrixResult;
  128. bool owned;
  129. Formula_Result () {
  130. our expressionType = kFormula_EXPRESSION_TYPE_NUMERIC;
  131. our numericResult = 0.0;
  132. our stringResult = autostring32();
  133. our numericVectorResult = VEC ();
  134. our numericMatrixResult = MAT ();
  135. our owned = false;
  136. }
  137. void reset () {
  138. our stringResult. reset();
  139. if (our owned) {
  140. {// scope
  141. autoVEC removable;
  142. removable. adoptFromAmbiguousOwner (our numericVectorResult);
  143. }
  144. our numericVectorResult = VEC (); // undangle
  145. {// scope
  146. autoMAT mat;
  147. mat. adoptFromAmbiguousOwner (our numericMatrixResult);
  148. }
  149. our numericMatrixResult = MAT (); // undangle
  150. }
  151. }
  152. ~ Formula_Result () {
  153. our reset();
  154. }
  155. };
  156. Thing_declare (Interpreter);
  157. void Formula_compile (Interpreter interpreter, Daata data, conststring32 expression, int expressionType, bool optimize);
  158. void Formula_run (integer row, integer col, Formula_Result *result);
  159. /* End of file Formula.h */
  160. #endif