/[svn]/linuxsampler/trunk/src/scriptvm/common.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/scriptvm/common.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3581 - (show annotations) (download)
Fri Aug 30 11:40:25 2019 UTC (22 months, 3 weeks ago) by schoenebeck
File size: 8548 byte(s)
NKSP: Allow more wider support of standard measuring units & 'final'ness.

* Raised compiler requirement to be C++14 compliant (due to severe
  restrictions regarding C-style aggregate initializer lists in C++11
  which are now massively used throughout the code base).

* NKSP VM API: Allow units and 'final'ness to be returned as result from
  built-in functions (added methods VMFunction::returnUnitType() and
  VMFunction::returnsFinal() for that purpose which must be implemented by
  built-in function implementations).

* NKSP language: Allow metric unit prefixes of numeric scalar and array
  variables to be changed freely at runtime (unlike unit types like Hz etc.
  which are still sticky parse-time features of variables which cannot be
  changed at runtime for the intentional sake of determinism).

* NKSP language: 'final' values are prohibited for array variables for now
  (attempt causes a parsers error).

* NKSP language: expressions with unit types (e.g. Hz) are prohibited for
  conditions of runtime control structures like if(), while(), select()
  (attempt causes a parser error).

* NKSP VM API: Allow built-in functions to perform their own, individual
  parse time checks of arguments going to be passed to the function at
  runtime (added method VMFunction::checkArgs() for that purpose).

* NKSP language: raise parser warning if only one operand of binary
  operators (like logical 'or' comparison) contain a 'final' value (because
  it would always yield in a 'final' result in such cases).

* NKSP language: Allow comparison (=, #, <, >, <=, >=) of values with
  different metric unit prefixes, which will behave as expected (e.g.
  result of expression '1000us < 2ms' is true).

* NKSP language: Allow adding values with different metric unit prefixes
  (e.g. result of expression '100Hz + 5kHz' is '5100Hz').

* NKSP language: Allow subtracting values with different metric unit
  prefixes (e.g. result of expression '1ms - 20us' is '980us').

* NKSP language: Allow multiplying with any metric unit prefixes
  (e.g. result of expression '2k * 3ms' is '6s'), however multiplications
  with unit types on both sides (e.g. '2s * 2s') is still prohibited since
  we don't have any considerable practical use for a term like '4s^2'
  (hence any attempt multiplying two unit types still causes parser error).

* NKSP language: Allow dividing by any metric unit prefixes and allow
  division of same unit type on both sides (e.g. expression '8kHz / 1000Hz'
  yields in unit free result '8'). So this is now a way to cast units away
  e.g. for passing the result to other expressions, certain function calls
  or variables which are not accepting any units (or that specific unit).

* NKSP language: integer arrays and real number arrays can now be converted
  to strings (e.g. for dumping their content with message() calls for
  script debugging purposes).

* NKSP language: expressions and variables with units are now correctly
  casted to strings (e.g. with message() calls).

* NKSP language: comparing real numbers for equalness (e.g. '~foo = 3.1') or
  unequalness (e.g. '~foo # 3.1') is now less strict and takes the expected
  floating point tolerances into account.

* NKSP VM API: Added methods VMScalarNumberExpr::evalCastInt() and
  VMScalarNumberExpr::evalCastReal().

* NKSP VM API: Added base class 'VMNumberArrayExpr' for classes
  'VMIntArrayExpr' and 'VMRealArrayExpr'.

* NKSP VM API: replaced all unitPrefix() (parse time) methods by
  unitFactor() (runtime) methods.

* Built-in function "exit()" supports now returning units and 'final'ness
  exclusively for test cases.

* The following built-in functions support now units as well: "abs()",
  "random()", "inc()", "dec()", "in_range()", "min()", "max()",
  "real_to_int()", "int()", "int_to_real()" and "real()".

* Built-in functions "array_equal()", "search()" and "sort()" support now
  real number arrays (correctly) as well.

* Added individual parse time checks of arguments to be passed to built-in
  functions "random()", "inc()", "dec()", "in_range()", "min()", "max()",
  "array_equal()" and "search()" specific for their individual purposes.

* Test cases: Added massive amount of NKSP test cases for standard
  measuring units and 'final' operator usage cases.

* Test cases: Added NKSP test cases for (floating point tolerance aware)
  real number equalness / unequalness comparison.

* Bumped version (2.1.1.svn8).

1 /*
2 * Copyright (c) 2014-2019 Christian Schoenebeck
3 *
4 * http://www.linuxsampler.org
5 *
6 * This file is part of LinuxSampler and released under the same terms.
7 * See README file for details.
8 */
9
10 #include "common.h"
11 #include <iostream>
12 #include "editor/SourceToken.h"
13
14 namespace LinuxSampler {
15
16 ///////////////////////////////////////////////////////////////////////
17 // class 'VMUnit'
18
19 static vmfloat _unitFactor(MetricPrefix_t prefix) {
20 switch (prefix) {
21 case VM_NO_PREFIX: return 1.f;
22 case VM_KILO: return 1000.f;
23 case VM_HECTO: return 100.f;
24 case VM_DECA: return 10.f;
25 case VM_DECI: return 0.1f;
26 case VM_CENTI: return 0.01f;
27 case VM_MILLI: return 0.001f;
28 case VM_MICRO: return 0.000001f;
29 }
30 return 1.f;
31 }
32
33 vmfloat VMUnit::unitFactor(MetricPrefix_t prefix) {
34 return _unitFactor(prefix);
35 }
36
37 vmfloat VMUnit::unitFactor(MetricPrefix_t prefix1, MetricPrefix_t prefix2) {
38 return _unitFactor(prefix1) * _unitFactor(prefix2);
39 }
40
41 vmfloat VMUnit::unitFactor(const MetricPrefix_t* prefixes, vmuint size) {
42 vmfloat f = VM_NO_FACTOR;
43 for (vmuint i = 0; i < size && prefixes[i]; ++i)
44 f *= _unitFactor(prefixes[i]);
45 return f;
46 }
47
48 bool VMUnit::hasUnitFactorNow() const {
49 return unitFactor() != VM_NO_FACTOR;
50 }
51
52 ///////////////////////////////////////////////////////////////////////
53 // class 'VMExpr'
54
55 VMIntExpr* VMExpr::asInt() const {
56 return const_cast<VMIntExpr*>( dynamic_cast<const VMIntExpr*>(this) );
57 }
58
59 VMRealExpr* VMExpr::asReal() const {
60 return const_cast<VMRealExpr*>( dynamic_cast<const VMRealExpr*>(this) );
61 }
62
63 VMScalarNumberExpr* VMExpr::asScalarNumberExpr() const {
64 return const_cast<VMScalarNumberExpr*>(
65 dynamic_cast<const VMScalarNumberExpr*>(this)
66 );
67 }
68
69 VMStringExpr* VMExpr::asString() const {
70 return const_cast<VMStringExpr*>( dynamic_cast<const VMStringExpr*>(this) );
71 }
72
73 VMIntArrayExpr* VMExpr::asIntArray() const {
74 return const_cast<VMIntArrayExpr*>( dynamic_cast<const VMIntArrayExpr*>(this) );
75 }
76
77 VMRealArrayExpr* VMExpr::asRealArray() const {
78 return const_cast<VMRealArrayExpr*>(
79 dynamic_cast<const VMRealArrayExpr*>(this)
80 );
81 }
82
83 VMArrayExpr* VMExpr::asArray() const {
84 return const_cast<VMArrayExpr*>(
85 dynamic_cast<const VMArrayExpr*>(this)
86 );
87 }
88
89 bool VMExpr::isModifyable() const {
90 const VMVariable* var = dynamic_cast<const VMVariable*>(this);
91 return (!var) ? false : var->isAssignable();
92 }
93
94 bool VMFunction::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {
95 return type == VM_NO_UNIT;
96 }
97
98 bool VMFunction::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
99 return false;
100 }
101
102 bool VMFunction::acceptsArgFinal(vmint iArg) const {
103 return false;
104 }
105
106 void VMFunction::checkArgs(VMFnArgs* args,
107 std::function<void(String)> err,
108 std::function<void(String)> wrn)
109 {
110 }
111
112 void VMFunction::wrnMsg(const String& txt) {
113 std::cout << "[ScriptVM] " << txt << std::endl;
114 }
115
116 void VMFunction::errMsg(const String& txt) {
117 std::cerr << "[ScriptVM] " << txt << std::endl;
118 }
119
120 ///////////////////////////////////////////////////////////////////////
121 // class 'VMScalarNumberExpr'
122
123 vmint VMScalarNumberExpr::evalCastInt() {
124 if (exprType() == INT_EXPR)
125 return asInt()->evalInt();
126 else
127 return vmint( asReal()->evalReal() );
128 }
129
130 vmfloat VMScalarNumberExpr::evalCastReal() {
131 if (exprType() == REAL_EXPR)
132 return asReal()->evalReal();
133 else
134 return vmfloat( asInt()->evalInt() );
135 }
136
137 ///////////////////////////////////////////////////////////////////////
138 // class 'VMIntExpr'
139
140 vmint VMIntExpr::evalInt(MetricPrefix_t prefix) {
141 vmfloat f = (vmfloat) evalInt();
142 vmfloat factor = unitFactor() / _unitFactor(prefix);
143 return (vmint) f * factor;
144 }
145
146 vmint VMIntExpr::evalInt(MetricPrefix_t prefix1, MetricPrefix_t prefix2) {
147 vmfloat f = (vmfloat) evalInt();
148 vmfloat factor = unitFactor() /
149 ( _unitFactor(prefix1) * _unitFactor(prefix2) );
150 return (vmint) f * factor;
151 }
152
153 ///////////////////////////////////////////////////////////////////////
154 // class 'VMRealExpr'
155
156 vmfloat VMRealExpr::evalReal(MetricPrefix_t prefix) {
157 vmfloat f = evalReal();
158 vmfloat factor = unitFactor() / _unitFactor(prefix);
159 return f * factor;
160 }
161
162 vmfloat VMRealExpr::evalReal(MetricPrefix_t prefix1, MetricPrefix_t prefix2) {
163 vmfloat f = evalReal();
164 vmfloat factor = unitFactor() /
165 ( _unitFactor(prefix1) * _unitFactor(prefix2) );
166 return f * factor;
167 }
168
169 ///////////////////////////////////////////////////////////////////////
170 // class 'VMSourceToken'
171
172 VMSourceToken::VMSourceToken() : m_token(NULL) {
173 }
174
175 VMSourceToken::VMSourceToken(SourceToken* ct) : m_token(ct) {
176 }
177
178 VMSourceToken::VMSourceToken(const VMSourceToken& other) {
179 if (other.m_token) {
180 m_token = new SourceToken;
181 *m_token = *other.m_token;
182 } else m_token = NULL;
183 }
184
185 VMSourceToken::~VMSourceToken() {
186 if (m_token) {
187 delete m_token;
188 m_token = NULL;
189 }
190 }
191
192 VMSourceToken& VMSourceToken::operator=(const VMSourceToken& other) {
193 if (m_token) delete m_token;
194 if (other.m_token) {
195 m_token = new SourceToken;
196 *m_token = *other.m_token;
197 } else m_token = NULL;
198 return *this;
199 }
200
201 String VMSourceToken::text() const {
202 return (m_token) ? m_token->text() : "";
203 }
204
205 int VMSourceToken::firstLine() const {
206 return (m_token) ? m_token->firstLine() : 0;
207 }
208
209 int VMSourceToken::firstColumn() const {
210 return (m_token) ? m_token->firstColumn() : 0;
211 }
212
213 bool VMSourceToken::isEOF() const {
214 return (m_token) ? m_token->isEOF() : true;
215 }
216
217 bool VMSourceToken::isNewLine() const {
218 return (m_token) ? m_token->isNewLine() : false;
219 }
220
221 bool VMSourceToken::isKeyword() const {
222 return (m_token) ? m_token->isKeyword() : false;
223 }
224
225 bool VMSourceToken::isVariableName() const {
226 return (m_token) ? m_token->isVariableName() : false;
227 }
228
229 bool VMSourceToken::isIdentifier() const {
230 return (m_token) ? m_token->isIdentifier() : false;
231 }
232
233 bool VMSourceToken::isNumberLiteral() const {
234 return (m_token) ? m_token->isNumberLiteral() : false;
235 }
236
237 bool VMSourceToken::isStringLiteral() const {
238 return (m_token) ? m_token->isStringLiteral() : false;
239 }
240
241 bool VMSourceToken::isComment() const {
242 return (m_token) ? m_token->isComment() : false;
243 }
244
245 bool VMSourceToken::isPreprocessor() const {
246 return (m_token) ? m_token->isPreprocessor() : false;
247 }
248
249 bool VMSourceToken::isMetricPrefix() const {
250 return (m_token) ? m_token->isMetricPrefix() : false;
251 }
252
253 bool VMSourceToken::isStdUnit() const {
254 return (m_token) ? m_token->isStdUnit() : false;
255 }
256
257 bool VMSourceToken::isOther() const {
258 return (m_token) ? m_token->isOther() : true;
259 }
260
261 bool VMSourceToken::isIntegerVariable() const {
262 return (m_token) ? m_token->isIntegerVariable() : false;
263 }
264
265 bool VMSourceToken::isRealVariable() const {
266 return (m_token) ? m_token->isRealVariable() : false;
267 }
268
269 bool VMSourceToken::isStringVariable() const {
270 return (m_token) ? m_token->isStringVariable() : false;
271 }
272
273 bool VMSourceToken::isIntArrayVariable() const {
274 return (m_token) ? m_token->isIntegerArrayVariable() : false;
275 }
276
277 bool VMSourceToken::isRealArrayVariable() const {
278 return (m_token) ? m_token->isRealArrayVariable() : false;
279 }
280
281 bool VMSourceToken::isArrayVariable() const { // deprecated API: will be removed !
282 return isIntArrayVariable();
283 }
284
285 bool VMSourceToken::isEventHandlerName() const {
286 return (m_token) ? m_token->isEventHandlerName() : false;
287 }
288
289 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC