1 /*
2  *  cDirectInterpretASTVisitor.cc
3  *  Avida
4  *
5  *  Created by David on 3/4/08.
6  *  Copyright 2008-2011 Michigan State University. All rights reserved.
7  *
8  *
9  *  This file is part of Avida.
10  *
11  *  Avida is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License
12  *  as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
13  *
14  *  Avida is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public License along with Avida.
18  *  If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #include "cDirectInterpretASTVisitor.h"
23 
24 #include <cassert>
25 #include <cmath>
26 
27 #include "avida/Avida.h"
28 #include "AvidaScript.h"
29 
30 #include "cASFunction.h"
31 #include "cStringUtil.h"
32 #include "cSymbolTable.h"
33 
34 #include "tMatrix.h"
35 
36 using namespace AvidaScript;
37 
38 
39 #ifndef DEBUG_AS_DIRECT_INTERPRET
40 #define DEBUG_AS_DIRECT_INTERPRET 1
41 #endif
42 
43 #define INTERPRET_ERROR(code, ...) reportError(AS_DIRECT_INTERPRET_ERR_ ## code, node.GetFilePosition(),  __LINE__, ##__VA_ARGS__)
44 
45 #define TOKEN(x) AS_TOKEN_ ## x
46 #define TYPE(x) AS_TYPE_ ## x
47 
48 
cDirectInterpretASTVisitor(cSymbolTable * global_symtbl)49 cDirectInterpretASTVisitor::cDirectInterpretASTVisitor(cSymbolTable* global_symtbl)
50   : m_global_symtbl(global_symtbl), m_cur_symtbl(global_symtbl), m_rtype(TYPE(INVALID)), m_call_stack(0, 2048), m_sp(0)
51   , m_has_returned(false), m_obj_assign(false)
52 {
53   m_call_stack.Resize(m_global_symtbl->GetNumVariables());
54   for (int i = 0; i < m_global_symtbl->GetNumVariables(); i++) {
55     switch (m_global_symtbl->GetVariableType(i).type) {
56       case TYPE(ARRAY):       m_call_stack[i].value.as_array = new cLocalArray; break;
57       case TYPE(BOOL):        m_call_stack[i].value.as_bool = false; break;
58       case TYPE(CHAR):        m_call_stack[i].value.as_char = 0; break;
59       case TYPE(DICT):        m_call_stack[i].value.as_dict = new cLocalDict; break;
60       case TYPE(INT):         m_call_stack[i].value.as_int = 0; break;
61       case TYPE(FLOAT):       m_call_stack[i].value.as_float = 0.0; break;
62       case TYPE(MATRIX):      m_call_stack[i].value.as_matrix = NULL; break;
63       case TYPE(STRING):      m_call_stack[i].value.as_string = NULL; break;
64 
65       case TYPE(OBJECT_REF):
66         m_call_stack[i].value.as_ref = NULL;
67         m_call_stack[i].type.info = m_global_symtbl->GetVariableType(i).info;
68         break;
69 
70       default: break;
71     }
72   }
73 }
74 
~cDirectInterpretASTVisitor()75 cDirectInterpretASTVisitor::~cDirectInterpretASTVisitor()
76 {
77   for (int i = 0; i < m_global_symtbl->GetNumVariables(); i++) {
78     ASType_t type = m_global_symtbl->GetVariableType(i).type;
79     if (type == TYPE(VAR)) type = m_call_stack[i].type.type;
80 
81     switch (type) {
82       case TYPE(ARRAY):       m_call_stack[i].value.as_array->RemoveReference(); break;
83       case TYPE(BOOL):        break;
84       case TYPE(CHAR):        break;
85       case TYPE(DICT):        m_call_stack[i].value.as_dict->RemoveReference(); break;
86       case TYPE(INT):         break;
87       case TYPE(FLOAT):       break;
88       case TYPE(MATRIX):      m_call_stack[i].value.as_matrix->RemoveReference(); break;
89       case TYPE(OBJECT_REF):  delete m_call_stack[i].value.as_ref; break;
90       case TYPE(STRING):      delete m_call_stack[i].value.as_string; break;
91       default: break;
92     }
93   }
94 
95 }
96 
97 
Interpret(cASTNode * node)98 int cDirectInterpretASTVisitor::Interpret(cASTNode* node)
99 {
100   node->Accept(*this);
101 
102   if (m_has_returned) return asInt(m_rtype, m_rvalue, *node);
103 
104   return 0;
105 }
106 
107 
VisitAssignment(cASTAssignment & node)108 void cDirectInterpretASTVisitor::VisitAssignment(cASTAssignment& node)
109 {
110   cSymbolTable* symtbl = node.IsVarGlobal() ? m_global_symtbl : m_cur_symtbl;
111   int sp = node.IsVarGlobal() ? 0 : m_sp;
112   int var_id = node.GetVarID();
113 
114   node.GetExpression()->Accept(*this);
115 
116   switch (symtbl->GetVariableType(var_id).type) {
117     case TYPE(BOOL):        m_call_stack[sp + var_id].value.as_bool = asBool(m_rtype, m_rvalue, node); break;
118     case TYPE(CHAR):        m_call_stack[sp + var_id].value.as_char = asChar(m_rtype, m_rvalue, node); break;
119     case TYPE(FLOAT):       m_call_stack[sp + var_id].value.as_float = asFloat(m_rtype, m_rvalue, node); break;
120     case TYPE(INT):         m_call_stack[sp + var_id].value.as_int = asInt(m_rtype, m_rvalue, node); break;
121 
122     case TYPE(OBJECT_REF):
123       m_call_stack[sp + var_id].value.as_nobj->RemoveReference();
124       m_call_stack[sp + var_id].value.as_nobj = asNativeObject(symtbl->GetVariableType(var_id).info, m_rtype, m_rvalue, node);
125 
126     case TYPE(VAR):
127       m_call_stack[sp + var_id].value = m_rvalue;
128       m_call_stack[sp + var_id].type = m_rtype;
129       break;
130 
131     case TYPE(ARRAY):
132       m_call_stack[sp + var_id].value.as_array->RemoveReference();
133       m_call_stack[sp + var_id].value.as_array = asArray(m_rtype, m_rvalue, node);
134       break;
135 
136 
137     case TYPE(DICT):
138       m_call_stack[sp + var_id].value.as_dict->RemoveReference();
139       m_call_stack[sp + var_id].value.as_dict = asDict(m_rtype, m_rvalue, node);
140       break;
141 
142 
143     case TYPE(MATRIX):
144       m_call_stack[sp + var_id].value.as_matrix->RemoveReference();
145       m_call_stack[sp + var_id].value.as_matrix = asMatrix(m_rtype, m_rvalue, node);
146       break;
147 
148     case TYPE(STRING):
149       delete m_call_stack[sp + var_id].value.as_string;
150       m_call_stack[sp + var_id].value.as_string = asString(m_rtype, m_rvalue, node);
151       break;
152 
153     default:
154       INTERPRET_ERROR(INTERNAL);
155   }
156 }
157 
158 
VisitArgumentList(cASTArgumentList & node)159 void cDirectInterpretASTVisitor::VisitArgumentList(cASTArgumentList& node)
160 {
161   // Should never recurse into here.  Argument lists are processed by their owners as needed.
162   INTERPRET_ERROR(INTERNAL);
163 }
164 
165 
VisitObjectAssignment(cASTObjectAssignment & node)166 void cDirectInterpretASTVisitor::VisitObjectAssignment(cASTObjectAssignment& node)
167 {
168   m_obj_assign = true;
169   node.GetTarget()->Accept(*this);
170   m_obj_assign = false;
171   cObjectRef* obj = m_rvalue.as_ref;
172 
173   node.GetExpression()->Accept(*this);
174 
175   sAggregateValue val(m_rtype, m_rvalue);
176   if (!obj->Set(val)) {
177     val.Cleanup();
178     INTERPRET_ERROR(OBJECT_ASSIGN_FAIL);
179   }
180 }
181 
182 
183 
VisitReturnStatement(cASTReturnStatement & node)184 void cDirectInterpretASTVisitor::VisitReturnStatement(cASTReturnStatement& node)
185 {
186   node.GetExpression()->Accept(*this);
187   m_has_returned = true;
188 }
189 
190 
VisitStatementList(cASTStatementList & node)191 void cDirectInterpretASTVisitor::VisitStatementList(cASTStatementList& node)
192 {
193   tListIterator<cASTNode> it = node.Iterator();
194 
195   cASTNode* stmt = NULL;
196   while (!m_has_returned && (stmt = it.Next())) {
197     stmt->Accept(*this);
198   }
199 }
200 
201 
202 
VisitForeachBlock(cASTForeachBlock & node)203 void cDirectInterpretASTVisitor::VisitForeachBlock(cASTForeachBlock& node)
204 {
205   int var_id = node.GetVariable()->GetVarID();
206   sASTypeInfo var_type = node.GetVariable()->GetType();
207 
208   node.GetValues()->Accept(*this);
209   cLocalArray* arr = asArray(m_rtype, m_rvalue, node);
210 
211   int var_idx = m_sp + var_id;
212   for (int i = 0; i < arr->GetSize(); i++) {
213     // Set the variable value for this iteration
214     const sAggregateValue& val = arr->Get(i);
215     switch (var_type.type) {
216       case TYPE(BOOL):        m_call_stack[var_idx].value.as_bool = asBool(val.type, val.value, node); break;
217       case TYPE(CHAR):        m_call_stack[var_idx].value.as_char = asChar(val.type, val.value, node); break;
218       case TYPE(FLOAT):       m_call_stack[var_idx].value.as_float = asFloat(val.type, val.value, node); break;
219       case TYPE(INT):         m_call_stack[var_idx].value.as_int = asInt(val.type, val.value, node); break;
220       case TYPE(OBJECT_REF):
221         m_call_stack[var_idx].value.as_nobj->RemoveReference();
222         m_call_stack[var_idx].value.as_nobj = asNativeObject(var_type.info, val.type, val.value, node);
223         break;
224 
225       case TYPE(ARRAY):
226         m_call_stack[var_idx].value.as_array->RemoveReference();
227         m_call_stack[var_idx].value.as_array = asArray(val.type, val.value, node);
228         break;
229 
230       case TYPE(DICT):
231         m_call_stack[var_idx].value.as_dict->RemoveReference();
232         m_call_stack[var_idx].value.as_dict = asDict(val.type, val.value, node);
233         break;
234 
235       case TYPE(VAR):
236         m_call_stack[var_idx].value = val.value;
237         m_call_stack[var_idx].type = val.type;
238         break;
239 
240       case TYPE(MATRIX):
241         m_call_stack[var_idx].value.as_matrix->RemoveReference();
242         m_call_stack[var_idx].value.as_matrix = asMatrix(val.type, val.value, node);
243         break;
244 
245       case TYPE(STRING):
246         delete m_call_stack[var_idx].value.as_string;
247         m_call_stack[var_idx].value.as_string = asString(val.type, val.value, node);
248         break;
249 
250       default:
251         INTERPRET_ERROR(INTERNAL);
252     }
253 
254     // Execute the body
255     node.GetCode()->Accept(*this);
256   }
257 
258   arr->RemoveReference();
259 }
260 
261 
VisitIfBlock(cASTIfBlock & node)262 void cDirectInterpretASTVisitor::VisitIfBlock(cASTIfBlock& node)
263 {
264   node.GetCondition()->Accept(*this);
265 
266   if (asBool(m_rtype, m_rvalue, node)) {
267     node.GetCode()->Accept(*this);
268   } else {
269     bool exec = false;
270     tListIterator<cASTIfBlock::cElseIf> it = node.ElseIfIterator();
271     cASTIfBlock::cElseIf* ei = NULL;
272     while ((ei = it.Next())) {
273       ei->GetCondition()->Accept(*this);
274       if (asBool(m_rtype, m_rvalue, node)) {
275         exec = true;
276         ei->GetCode()->Accept(*this);
277         break;
278       }
279     }
280 
281     if (!exec && node.HasElse()) node.GetElseCode()->Accept(*this);
282   }
283 }
284 
285 
VisitWhileBlock(cASTWhileBlock & node)286 void cDirectInterpretASTVisitor::VisitWhileBlock(cASTWhileBlock& node)
287 {
288   node.GetCondition()->Accept(*this);
289   while (asBool(m_rtype, m_rvalue, node)) {
290     node.GetCode()->Accept(*this);
291     node.GetCondition()->Accept(*this);
292   }
293 }
294 
295 
296 
VisitFunctionDefinition(cASTFunctionDefinition & node)297 void cDirectInterpretASTVisitor::VisitFunctionDefinition(cASTFunctionDefinition& node)
298 {
299   // Nothing to do here
300 }
301 
302 
VisitVariableDefinition(cASTVariableDefinition & node)303 void cDirectInterpretASTVisitor::VisitVariableDefinition(cASTVariableDefinition& node)
304 {
305   if (node.GetAssignmentExpression()) {
306     int var_id = node.GetVarID();
307 
308     node.GetAssignmentExpression()->Accept(*this);
309 
310     switch (node.GetType().type) {
311       case TYPE(ARRAY):       m_call_stack[m_sp + var_id].value.as_array = asArray(m_rtype, m_rvalue, node); break;
312       case TYPE(BOOL):        m_call_stack[m_sp + var_id].value.as_bool = asBool(m_rtype, m_rvalue, node); break;
313       case TYPE(CHAR):        m_call_stack[m_sp + var_id].value.as_char = asChar(m_rtype, m_rvalue, node); break;
314       case TYPE(DICT):        m_call_stack[m_sp + var_id].value.as_dict = asDict(m_rtype, m_rvalue, node); break;
315       case TYPE(FLOAT):       m_call_stack[m_sp + var_id].value.as_float = asFloat(m_rtype, m_rvalue, node); break;
316       case TYPE(INT):         m_call_stack[m_sp + var_id].value.as_int = asInt(m_rtype, m_rvalue, node); break;
317       case TYPE(OBJECT_REF):  m_call_stack[m_sp + var_id].value.as_nobj = asNativeObject(node.GetType().info, m_rtype, m_rvalue, node); break;
318       case TYPE(MATRIX):      m_call_stack[m_sp + var_id].value.as_matrix = asMatrix(m_rtype, m_rvalue, node); break;
319       case TYPE(STRING):
320         delete m_call_stack[m_sp + var_id].value.as_string;
321         m_call_stack[m_sp + var_id].value.as_string = asString(m_rtype, m_rvalue, node);
322         break;
323 
324       case TYPE(VAR):
325         m_call_stack[m_sp + var_id].value = m_rvalue;
326         m_call_stack[m_sp + var_id].type = m_rtype;
327         break;
328 
329       default:
330         INTERPRET_ERROR(INTERNAL);
331     }
332   } else if (node.GetDimensions()) {
333     if (node.GetType() == TYPE(ARRAY)) {
334       cASTNode* szn = node.GetDimensions()->Iterator().Next();
335       szn->Accept(*this);
336 
337       cLocalArray* arr = new cLocalArray();
338       arr->Resize(asInt(m_rtype, m_rvalue, node));
339       m_call_stack[m_sp + node.GetVarID()].value.as_array = arr;
340     } else if (node.GetType() == TYPE(MATRIX)) {
341       tListIterator<cASTNode> it = node.GetDimensions()->Iterator();
342       it.Next()->Accept(*this);
343       int sz_x = asInt(m_rtype, m_rvalue, node);
344       it.Next()->Accept(*this);
345       int sz_y = asInt(m_rtype, m_rvalue, node);
346 
347       cLocalMatrix* mat = new cLocalMatrix();
348       mat->Resize(sz_x, sz_y);
349       m_call_stack[m_sp + node.GetVarID()].value.as_matrix = mat;
350     } else {
351       INTERPRET_ERROR(INTERNAL);
352     }
353   } else if (node.GetType().type == TYPE(OBJECT_REF)) {
354     // @AS_TODO - set native object ref to special NULL value
355   }
356 }
357 
358 
VisitVariableDefinitionList(cASTVariableDefinitionList & node)359 void cDirectInterpretASTVisitor::VisitVariableDefinitionList(cASTVariableDefinitionList& node)
360 {
361   // Should never recurse into here.  Variable definition lists are processed by function definitions.
362   INTERPRET_ERROR(INTERNAL);
363 }
364 
365 
366 
VisitExpressionBinary(cASTExpressionBinary & node)367 void cDirectInterpretASTVisitor::VisitExpressionBinary(cASTExpressionBinary& node)
368 {
369   // Process the left and right side expressions
370   node.GetLeft()->Accept(*this);
371   uAnyType lval = m_rvalue;
372   sASTypeInfo ltype = m_rtype;
373   node.GetRight()->Accept(*this);
374   uAnyType rval = m_rvalue;
375   sASTypeInfo rtype = m_rtype;
376 
377 
378   switch (node.GetOperator()) {
379     case TOKEN(ARR_RANGE):
380       {
381         int l = asInt(ltype, lval, node);
382         int r = asInt(rtype, rval, node);
383         int sz = abs(r - l) + 1;
384 
385         cLocalArray* arr = new cLocalArray(sz);
386         uAnyType val;
387         if (r > l) {
388           for (int i = 0; i < sz; i++) {
389             val.as_int = l + i;
390             arr->Set(i, TYPE(INT), val);
391           }
392         } else {
393           for (int i = 0; i < sz; i++) {
394             val.as_int = l - i;
395             arr->Set(i, TYPE(INT), val);
396           }
397         }
398 
399         m_rvalue.as_array = arr;
400         m_rtype = TYPE(ARRAY);
401       }
402       break;
403 
404     case TOKEN(ARR_EXPAN):
405       {
406         int n = asInt(rtype, rval, node);
407         if (n < 0) INTERPRET_ERROR(INVALID_ARRAY_SIZE);
408 
409         cLocalArray* arr = new cLocalArray(n);
410         for (int i = 0; i < n; i++) arr->Set(i, ltype.type, lval);
411 
412         m_rvalue.as_array = arr;
413         m_rtype = TYPE(ARRAY);
414       }
415       break;
416 
417     case TOKEN(OP_LOGIC_AND):
418     case TOKEN(OP_LOGIC_OR):
419       {
420         bool l = asBool(ltype, lval, node);
421         bool r = asBool(rtype, rval, node);
422         m_rvalue.as_bool = (node.GetOperator() == TOKEN(OP_LOGIC_AND)) ? (l && r) : (l || r);
423         m_rtype = TYPE(BOOL);
424       }
425       break;
426 
427     case TOKEN(OP_BIT_AND):
428     case TOKEN(OP_BIT_OR):
429       {
430         sASTypeInfo rettype = node.GetType();
431 
432         // Determine the operation type if it is a runtime decision
433         if (rettype == TYPE(RUNTIME)) rettype = getRuntimeType(ltype.type, rtype.type);
434 
435         if (rettype == TYPE(CHAR)) {
436           int l = asChar(ltype, lval, node);
437           int r = asChar(rtype, rval, node);
438           m_rvalue.as_char = (node.GetOperator() == TOKEN(OP_BIT_AND)) ? (l & r) : (l | r);
439           m_rtype = TYPE(CHAR);
440         } else if (rettype == TYPE(INT)) {
441           int l = asInt(ltype, lval, node);
442           int r = asInt(rtype, rval, node);
443           m_rvalue.as_int = (node.GetOperator() == TOKEN(OP_BIT_AND)) ? (l & r) : (l | r);
444           m_rtype = TYPE(INT);
445         } else {
446           INTERPRET_ERROR(UNDEFINED_TYPE_OP, mapToken(node.GetOperator()), mapType(rettype));
447         }
448       }
449       break;
450 
451     case TOKEN(OP_EQ):
452     case TOKEN(OP_NEQ):
453       {
454         ASType_t comptype = node.GetCompareType().type;
455 
456         // Determine the operation type if it is a runtime decision
457         if (comptype == TYPE(RUNTIME)) comptype = getRuntimeType(ltype.type, rtype.type);
458 
459         switch (comptype) {
460           case TYPE(BOOL):
461             {
462               bool l = asBool(ltype, lval, node);
463               bool r = asBool(rtype, rval, node);
464               m_rvalue.as_bool = (node.GetOperator() == TOKEN(OP_EQ)) ? (l == r) : (l != r);
465             }
466             break;
467 
468           case TYPE(CHAR):
469           case TYPE(INT):
470             // Handle both char and int as integers
471             {
472               int l = asInt(ltype, lval, node);
473               int r = asInt(rtype, rval, node);
474               m_rvalue.as_bool = (node.GetOperator() == TOKEN(OP_EQ)) ? (l == r) : (l != r);
475             }
476             break;
477 
478           case TYPE(FLOAT):
479             {
480               double l = asFloat(ltype, lval, node);
481               double r = asFloat(rtype, rval, node);
482               m_rvalue.as_bool = (node.GetOperator() == TOKEN(OP_EQ)) ? (l == r) : (l != r);
483             }
484             break;
485 
486           case TYPE(STRING):
487             {
488               cString* l = asString(ltype, lval, node);
489               cString* r = asString(rtype, rval, node);
490               m_rvalue.as_bool = (node.GetOperator() == TOKEN(OP_EQ)) ? (*l == *r) : (*l != *r);
491               delete l;
492               delete r;
493             }
494             break;
495 
496           default:
497             INTERPRET_ERROR(UNDEFINED_TYPE_OP, mapToken(node.GetOperator()), mapType(comptype));
498         }
499 
500         m_rtype = TYPE(BOOL);
501       }
502       break;
503 
504     case TOKEN(OP_LE):
505     case TOKEN(OP_GE):
506     case TOKEN(OP_LT):
507     case TOKEN(OP_GT):
508       {
509         ASType_t comptype = node.GetCompareType().type;
510 
511         // Determine the operation type if it is a runtime decision
512         if (comptype == TYPE(RUNTIME)) comptype = getRuntimeType(ltype.type, rtype.type);
513 
514         switch (comptype) {
515           case TYPE(CHAR):
516           case TYPE(INT):
517             // Handle both char and int as integers
518             {
519               int l = asInt(ltype, lval, node);
520               int r = asInt(rtype, rval, node);
521               switch (node.GetOperator()) {
522                 case TOKEN(OP_LE): m_rvalue.as_bool = (l <= r); break;
523                 case TOKEN(OP_GE): m_rvalue.as_bool = (l >= r); break;
524                 case TOKEN(OP_LT): m_rvalue.as_bool = (l < r); break;
525                 case TOKEN(OP_GT): m_rvalue.as_bool = (l > r); break;
526                 default: INTERPRET_ERROR(INTERNAL);
527               }
528             }
529             break;
530 
531           case TYPE(FLOAT):
532             {
533               double l = asFloat(ltype, lval, node);
534               double r = asFloat(rtype, rval, node);
535               switch (node.GetOperator()) {
536                 case TOKEN(OP_LE): m_rvalue.as_bool = (l <= r); break;
537                 case TOKEN(OP_GE): m_rvalue.as_bool = (l >= r); break;
538                 case TOKEN(OP_LT): m_rvalue.as_bool = (l < r); break;
539                 case TOKEN(OP_GT): m_rvalue.as_bool = (l > r); break;
540                 default: INTERPRET_ERROR(INTERNAL);
541               }
542             }
543             break;
544 
545           default:
546             INTERPRET_ERROR(UNDEFINED_TYPE_OP, mapToken(node.GetOperator()), mapType(comptype));
547         }
548 
549         m_rtype = TYPE(BOOL);
550       }
551       break;
552 
553 
554     case TOKEN(OP_ADD):
555       {
556         ASType_t rettype = node.GetType().type;
557 
558         // Determine the operation type if it is a runtime decision
559         if (rettype == TYPE(RUNTIME)) rettype = getRuntimeType(ltype.type, rtype.type, true);
560 
561         switch (rettype) {
562           case TYPE(CHAR):    m_rvalue.as_char = asChar(ltype, lval, node) + asChar(rtype, rval, node); break;
563           case TYPE(INT):     m_rvalue.as_int = asInt(ltype, lval, node) + asInt(rtype, rval, node); break;
564           case TYPE(FLOAT):   m_rvalue.as_float = asFloat(ltype, lval, node) + asFloat(rtype, rval, node); break;
565           case TYPE(MATRIX):  matrixAdd(asMatrix(ltype, lval, node), asMatrix(rtype, rval, node), node); break;
566 
567           case TYPE(STRING):
568             {
569               cString* l = asString(ltype, lval, node);
570               cString* r = asString(rtype, rval, node);
571               m_rvalue.as_string = new cString(*l + *r);
572               delete l;
573               delete r;
574             }
575             break;
576 
577           case TYPE(ARRAY):
578             {
579               cLocalArray* l = asArray(ltype, lval, node);
580               cLocalArray* r = asArray(rtype, rval, node);
581               m_rvalue.as_array = new cLocalArray(l, r);
582               l->RemoveReference();
583               r->RemoveReference();
584             }
585             break;
586 
587           default:
588             INTERPRET_ERROR(UNDEFINED_TYPE_OP, mapToken(TOKEN(OP_ADD)), mapType(rettype));
589         }
590 
591         m_rtype = rettype;
592       }
593       break;
594 
595     case TOKEN(OP_SUB):
596       {
597         ASType_t rettype = node.GetType().type;
598 
599         // Determine the operation type if it is a runtime decision
600         if (rettype == TYPE(RUNTIME)) rettype = getRuntimeType(ltype.type, rtype.type);
601 
602         switch (rettype) {
603           case TYPE(CHAR):    m_rvalue.as_char = asChar(ltype, lval, node) - asChar(rtype, rval, node); break;
604           case TYPE(INT):     m_rvalue.as_int = asInt(ltype, lval, node) - asInt(rtype, rval, node); break;
605           case TYPE(FLOAT):   m_rvalue.as_float = asFloat(ltype, lval, node) - asFloat(rtype, rval, node); break;
606           case TYPE(MATRIX):  matrixSubtract(asMatrix(ltype, lval, node), asMatrix(rtype, rval, node), node); break;
607 
608           default:
609             INTERPRET_ERROR(UNDEFINED_TYPE_OP, mapToken(TOKEN(OP_ADD)), mapType(rettype));
610         }
611 
612         m_rtype = rettype;
613       }
614       break;
615 
616     case TOKEN(OP_MUL):
617       {
618         ASType_t rettype = node.GetType().type;
619 
620         // Determine the operation type if it is a runtime decision
621         if (rettype == TYPE(RUNTIME)) rettype = getRuntimeType(ltype.type, rtype.type);
622 
623         switch (rettype) {
624           case TYPE(CHAR):    m_rvalue.as_char = asChar(ltype, lval, node) * asChar(rtype, rval, node); break;
625           case TYPE(INT):     m_rvalue.as_int = asInt(ltype, lval, node) * asInt(rtype, rval, node); break;
626           case TYPE(FLOAT):   m_rvalue.as_float = asFloat(ltype, lval, node) * asFloat(rtype, rval, node); break;
627           case TYPE(MATRIX):  matrixMultiply(asMatrix(ltype, lval, node), asMatrix(rtype, rval, node), node); break;
628 
629           default:
630             INTERPRET_ERROR(UNDEFINED_TYPE_OP, mapToken(TOKEN(OP_ADD)), mapType(rettype));
631         }
632 
633         m_rtype = rettype;
634       }
635       break;
636 
637     case TOKEN(OP_DIV):
638       {
639         ASType_t rettype = node.GetType().type;
640 
641         // Determine the operation type if it is a runtime decision
642         if (rettype == TYPE(RUNTIME)) rettype = getRuntimeType(ltype.type, rtype.type);
643 
644         switch (rettype) {
645           case TYPE(CHAR):
646             {
647               char r = asChar(rtype, rval, node);
648               if (r == 0) INTERPRET_ERROR(DIVISION_BY_ZERO);
649               m_rvalue.as_char = asChar(ltype, lval, node) / r;
650             }
651             break;
652           case TYPE(INT):
653             {
654               int r = asInt(rtype, rval, node);
655               if (r == 0) INTERPRET_ERROR(DIVISION_BY_ZERO);
656               m_rvalue.as_int = asInt(ltype, lval, node) / r;
657             }
658             break;
659           case TYPE(FLOAT):
660             {
661               double r = asFloat(rtype, rval, node);
662               if (r == 0.0) INTERPRET_ERROR(DIVISION_BY_ZERO);
663               m_rvalue.as_float = asFloat(ltype, lval, node) / r;
664             }
665             break;
666 
667           default:
668             INTERPRET_ERROR(UNDEFINED_TYPE_OP, mapToken(TOKEN(OP_ADD)), mapType(rettype));
669         }
670 
671         m_rtype = rettype;
672       }
673       break;
674 
675     case TOKEN(OP_MOD):
676       {
677         ASType_t rettype = node.GetType().type;
678 
679         // Determine the operation type if it is a runtime decision
680         if (rettype == TYPE(RUNTIME)) rettype = getRuntimeType(ltype.type, rtype.type);
681 
682         switch (rettype) {
683           case TYPE(CHAR):
684             {
685               char r = asChar(rtype, rval, node);
686               if (r == 0) INTERPRET_ERROR(DIVISION_BY_ZERO);
687               m_rvalue.as_char = asChar(ltype, lval, node) % r;
688             }
689             break;
690           case TYPE(INT):
691             {
692               int r = asInt(rtype, rval, node);
693               if (r == 0) INTERPRET_ERROR(DIVISION_BY_ZERO);
694               m_rvalue.as_int = asInt(ltype, lval, node) % r;
695             }
696             break;
697           case TYPE(FLOAT):
698             {
699               double r = asFloat(rtype, rval, node);
700               if (r == 0.0) INTERPRET_ERROR(DIVISION_BY_ZERO);
701               m_rvalue.as_float = fmod(asFloat(ltype, lval, node), r);
702             }
703             break;
704 
705           default:
706             INTERPRET_ERROR(UNDEFINED_TYPE_OP, mapToken(TOKEN(OP_ADD)), mapType(rettype));
707         }
708 
709         m_rtype = rettype;
710       }
711       break;
712 
713     case TOKEN(IDX_OPEN):
714       if (m_obj_assign) {
715         cObjectRef* obj = lval.as_ref;
716         sAggregateValue idx(rtype, rval);
717         sAggregateValue o_val;
718 
719         if (!obj->Get(o_val)) {
720           idx.Cleanup();
721           INTERPRET_ERROR(INDEX_ERROR);
722         }
723 
724         switch (o_val.type.type) {
725           case TYPE(ARRAY):
726           case TYPE(DICT):
727           case TYPE(MATRIX):
728           case TYPE(STRING):
729             break;
730 
731           default:
732             INTERPRET_ERROR(UNDEFINED_TYPE_OP, mapToken(TOKEN(IDX_OPEN)), mapType(o_val.type));
733         }
734 
735         m_rvalue.as_ref = new cObjectIndexRef(obj, idx);
736         m_rtype = TYPE(OBJECT_REF);
737       } else {
738 
739         switch (ltype.type) {
740           case TYPE(ARRAY):
741             {
742               cLocalArray* arr = lval.as_array;
743               int idx = asInt(rtype, rval, node);
744 
745               if (idx < 0 || idx >= arr->GetSize()) INTERPRET_ERROR(INDEX_OUT_OF_BOUNDS);
746 
747               const sAggregateValue val = arr->Get(idx);
748               m_rtype = val.type;
749               m_rvalue = val.value;
750 
751               arr->RemoveReference();
752             }
753             break;
754 
755           case TYPE(DICT):
756             {
757               cLocalDict* dict = lval.as_dict;
758               sAggregateValue idx(rtype, rval);
759 
760               sAggregateValue val;
761               if (!dict->Get(idx, val)) {
762                 idx.Cleanup();
763                 INTERPRET_ERROR(KEY_NOT_FOUND);
764               }
765 
766               idx.Cleanup();
767 
768               m_rtype = val.type;
769               m_rvalue = val.value;
770 
771               dict->RemoveReference();
772             }
773             break;
774 
775           case TYPE(MATRIX):
776             {
777               cLocalMatrix* mat = lval.as_matrix;
778               int idx = asInt(rtype, rval, node);
779 
780               if (idx < 0 || idx >= mat->GetNumRows()) INTERPRET_ERROR(INDEX_OUT_OF_BOUNDS);
781 
782               m_rtype = TYPE(ARRAY);
783               m_rvalue.as_array = mat->GetRow(idx);
784 
785               mat->RemoveReference();
786             }
787             break;
788 
789           case TYPE(STRING):
790             {
791               cString* str = lval.as_string;
792               int idx = asInt(rtype, rval, node);
793               if (idx < 0 || idx >= str->GetSize()) INTERPRET_ERROR(INDEX_OUT_OF_BOUNDS);
794 
795               m_rtype = TYPE(CHAR);
796               m_rvalue.as_char = (*str)[idx];
797               delete str;
798             }
799             break;
800 
801           default:
802             INTERPRET_ERROR(TYPE_CAST, mapType(ltype.type), mapType(TYPE(ARRAY)));
803         }
804 
805 
806       }
807       break;
808 
809     default:
810       // Parser should not allow an invalid operator to pass
811       INTERPRET_ERROR(INTERNAL);
812   }
813 }
814 
815 
VisitExpressionUnary(cASTExpressionUnary & node)816 void cDirectInterpretASTVisitor::VisitExpressionUnary(cASTExpressionUnary& node)
817 {
818   node.GetExpression()->Accept(*this);
819 
820   switch (node.GetOperator()) {
821     case TOKEN(OP_BIT_NOT):
822       switch (m_rtype.type) {
823         case TYPE(CHAR):
824           m_rvalue.as_char = ~m_rvalue.as_char;
825           break;
826         case TYPE(INT):
827           m_rvalue.as_int = ~m_rvalue.as_int;
828           break;
829 
830         default:
831           INTERPRET_ERROR(UNDEFINED_TYPE_OP, mapToken(TOKEN(OP_BIT_NOT)), mapType(m_rtype));
832       }
833       break;
834 
835     case TOKEN(OP_LOGIC_NOT):
836       m_rvalue.as_bool = !asBool(m_rtype, m_rvalue, node);
837       m_rtype = TYPE(BOOL);
838       break;
839 
840     case TOKEN(OP_SUB):
841       switch (m_rtype.type) {
842         case TYPE(CHAR):
843           m_rvalue.as_char = -m_rvalue.as_char;
844           break;
845         case TYPE(INT):
846           m_rvalue.as_int = -m_rvalue.as_int;
847           break;
848         case TYPE(FLOAT):
849           m_rvalue.as_float = -m_rvalue.as_float;
850           break;
851 
852         default:
853           INTERPRET_ERROR(UNDEFINED_TYPE_OP, mapToken(TOKEN(OP_BIT_NOT)), mapType(m_rtype));
854       }
855       break;
856 
857     default:
858       INTERPRET_ERROR(INTERNAL);
859   }
860 }
861 
862 
VisitBuiltInCall(cASTBuiltInCall & node)863 void cDirectInterpretASTVisitor::VisitBuiltInCall(cASTBuiltInCall& node)
864 {
865   cASTArgumentList* args = node.GetArguments();
866   cASTNode* trgt = node.GetTarget();
867 
868   switch (node.GetBuiltIn()) {
869     case AS_BUILTIN_CAST_BOOL:
870       args->Iterator().Next()->Accept(*this);
871       m_rvalue.as_bool = asBool(m_rtype, m_rvalue, node);
872       m_rtype = TYPE(BOOL);
873       break;
874 
875     case AS_BUILTIN_CAST_CHAR:
876       args->Iterator().Next()->Accept(*this);
877       m_rvalue.as_char = asChar(m_rtype, m_rvalue, node);
878       m_rtype = TYPE(CHAR);
879       break;
880 
881     case AS_BUILTIN_CAST_INT:
882       args->Iterator().Next()->Accept(*this);
883       m_rvalue.as_int = asInt(m_rtype, m_rvalue, node);
884       m_rtype = TYPE(INT);
885       break;
886 
887     case AS_BUILTIN_CAST_FLOAT:
888       args->Iterator().Next()->Accept(*this);
889       m_rvalue.as_float = asFloat(m_rtype, m_rvalue, node);
890       m_rtype = TYPE(FLOAT);
891       break;
892 
893     case AS_BUILTIN_CAST_STRING:
894       args->Iterator().Next()->Accept(*this);
895       m_rvalue.as_string = asString(m_rtype, m_rvalue, node);
896       m_rtype = TYPE(STRING);
897       break;
898 
899 
900     case AS_BUILTIN_IS_ARRAY:
901       args->Iterator().Next()->Accept(*this);
902       {
903         sAggregateValue val(m_rtype, m_rvalue);
904         val.Cleanup();
905       }
906       m_rvalue.as_bool = m_rtype.type == TYPE(ARRAY);
907       m_rtype = TYPE(BOOL);
908       break;
909 
910     case AS_BUILTIN_IS_BOOL:
911       args->Iterator().Next()->Accept(*this);
912       {
913         sAggregateValue val(m_rtype, m_rvalue);
914         val.Cleanup();
915       }
916       m_rvalue.as_bool = m_rtype.type == TYPE(BOOL);
917       m_rtype = TYPE(BOOL);
918       break;
919 
920     case AS_BUILTIN_IS_CHAR:
921       args->Iterator().Next()->Accept(*this);
922       {
923         sAggregateValue val(m_rtype, m_rvalue);
924         val.Cleanup();
925       }
926       m_rvalue.as_bool = m_rtype.type == TYPE(CHAR);
927       m_rtype = TYPE(BOOL);
928       break;
929 
930     case AS_BUILTIN_IS_DICT:
931       args->Iterator().Next()->Accept(*this);
932       {
933         sAggregateValue val(m_rtype, m_rvalue);
934         val.Cleanup();
935       }
936       m_rvalue.as_bool = m_rtype.type == TYPE(DICT);
937       m_rtype = TYPE(BOOL);
938       break;
939 
940     case AS_BUILTIN_IS_INT:
941       args->Iterator().Next()->Accept(*this);
942       {
943         sAggregateValue val(m_rtype, m_rvalue);
944         val.Cleanup();
945       }
946       m_rvalue.as_bool = m_rtype.type == TYPE(INT);
947       m_rtype = TYPE(BOOL);
948       break;
949 
950     case AS_BUILTIN_IS_FLOAT:
951       args->Iterator().Next()->Accept(*this);
952       {
953         sAggregateValue val(m_rtype, m_rvalue);
954         val.Cleanup();
955       }
956       m_rvalue.as_bool = m_rtype.type == TYPE(FLOAT);
957       m_rtype = TYPE(BOOL);
958       break;
959 
960     case AS_BUILTIN_IS_MATRIX:
961       args->Iterator().Next()->Accept(*this);
962       {
963         sAggregateValue val(m_rtype, m_rvalue);
964         val.Cleanup();
965       }
966       m_rvalue.as_bool = m_rtype.type == TYPE(MATRIX);
967       m_rtype = TYPE(BOOL);
968       break;
969 
970     case AS_BUILTIN_IS_STRING:
971       args->Iterator().Next()->Accept(*this);
972       {
973         sAggregateValue val(m_rtype, m_rvalue);
974         val.Cleanup();
975       }
976       m_rvalue.as_bool = m_rtype.type == TYPE(STRING);
977       m_rtype = TYPE(BOOL);
978       break;
979 
980 
981     case AS_BUILTIN_CLEAR:
982       trgt->Accept(*this);
983       if (m_rtype.type == TYPE(DICT)) {
984         m_rvalue.as_dict->Clear();
985         m_rvalue.as_dict->RemoveReference();
986       } else if (m_rtype.type == TYPE(MATRIX)) {
987         m_rvalue.as_matrix->Resize(0, 0);
988         m_rvalue.as_matrix->RemoveReference();
989       } else if (m_rtype.type == TYPE(ARRAY)) {
990         m_rvalue.as_array->Resize(0);
991         m_rvalue.as_array->RemoveReference();
992       } else {
993         INTERPRET_ERROR(UNDEFINED_TYPE_OP, "clear", mapType(m_rtype));
994       }
995       break;
996 
997     case AS_BUILTIN_COPY:
998       trgt->Accept(*this);
999       if (m_rtype.type == TYPE(ARRAY)) {
1000         cLocalArray* arr = new cLocalArray(m_rvalue.as_array);
1001         m_rvalue.as_array->RemoveReference();
1002         m_rvalue.as_array = arr;
1003       } else {
1004         INTERPRET_ERROR(UNDEFINED_TYPE_OP, "copy", mapType(m_rtype));
1005       }
1006       break;
1007 
1008     case AS_BUILTIN_HASKEY:
1009       trgt->Accept(*this);
1010       if (m_rtype.type == TYPE(DICT)) {
1011         cLocalDict* dict = m_rvalue.as_dict;
1012 
1013         args->Iterator().Next()->Accept(*this);
1014         sAggregateValue idx(m_rtype, m_rvalue);
1015         m_rvalue.as_bool = dict->HasKey(idx);
1016         idx.Cleanup();
1017         dict->RemoveReference();
1018 
1019         m_rtype = TYPE(BOOL);
1020       } else {
1021         INTERPRET_ERROR(UNDEFINED_TYPE_OP, "keys", mapType(m_rtype));
1022       }
1023       break;
1024 
1025 
1026     case AS_BUILTIN_KEYS:
1027       trgt->Accept(*this);
1028       if (m_rtype.type == TYPE(DICT)) {
1029         cLocalArray* arr = new cLocalArray();
1030         arr->SetWithKeys(m_rvalue.as_dict);
1031         m_rvalue.as_dict->RemoveReference();
1032         m_rvalue.as_array = arr;
1033         m_rtype = TYPE(ARRAY);
1034       } else {
1035         INTERPRET_ERROR(UNDEFINED_TYPE_OP, "keys", mapType(m_rtype));
1036       }
1037       break;
1038 
1039     case AS_BUILTIN_VALUES:
1040       trgt->Accept(*this);
1041       if (m_rtype.type == TYPE(DICT)) {
1042         cLocalArray* arr = new cLocalArray();
1043         arr->SetWithValues(m_rvalue.as_dict);
1044         m_rvalue.as_dict->RemoveReference();
1045         m_rvalue.as_array = arr;
1046         m_rtype = TYPE(ARRAY);
1047       } else {
1048         INTERPRET_ERROR(UNDEFINED_TYPE_OP, "values", mapType(m_rtype));
1049       }
1050       break;
1051 
1052 
1053     case AS_BUILTIN_LEN:
1054       trgt->Accept(*this);
1055       if (m_rtype == TYPE(STRING)) {
1056         int sz = m_rvalue.as_string->GetSize();
1057         delete m_rvalue.as_string;
1058         m_rvalue.as_int = sz;
1059       } else {
1060         cLocalArray* arr = asArray(m_rtype, m_rvalue, node);
1061         m_rvalue.as_int = arr->GetSize();
1062         arr->RemoveReference();
1063       }
1064       m_rtype = TYPE(INT);
1065       break;
1066 
1067     case AS_BUILTIN_REMOVE:
1068       trgt->Accept(*this);
1069       if (m_rtype.type == TYPE(DICT)) {
1070         cLocalDict* dict = m_rvalue.as_dict;
1071 
1072         if (!dict->IsShared()) {
1073           dict->RemoveReference();
1074           break;
1075         }
1076 
1077         args->Iterator().Next()->Accept(*this);
1078         sAggregateValue idx(m_rtype, m_rvalue);
1079         dict->Remove(idx);
1080         idx.Cleanup();
1081         dict->RemoveReference();
1082       } else if (m_rtype.type == TYPE(ARRAY)) {
1083         cLocalArray* arr = m_rvalue.as_array;
1084 
1085         if (!arr->IsShared()) {
1086           arr->RemoveReference();
1087           break;
1088         }
1089 
1090         args->Iterator().Next()->Accept(*this);
1091         int i = asInt(m_rtype, m_rvalue, node);
1092 
1093         if (i < 0 || i >= arr->GetSize()) INTERPRET_ERROR(INDEX_OUT_OF_BOUNDS);
1094 
1095         for (; i < (arr->GetSize() - 1); i++) arr->Set(i, arr->Get(i + 1));
1096         arr->Resize(arr->GetSize() - 1);
1097       } else {
1098         INTERPRET_ERROR(UNDEFINED_TYPE_OP, "remove", mapType(m_rtype));
1099       }
1100       break;
1101 
1102     case AS_BUILTIN_RESIZE:
1103       trgt->Accept(*this);
1104       if (m_rtype.type == TYPE(MATRIX)) {
1105         cLocalMatrix* mat = m_rvalue.as_matrix;
1106 
1107         if (args->GetSize() != 2) INTERPRET_ERROR(INVALID_ARRAY_SIZE);
1108 
1109         if (!mat->IsShared()) {
1110           mat->RemoveReference();
1111           break;
1112         }
1113 
1114         tListIterator<cASTNode> it = args->Iterator();
1115         it.Next()->Accept(*this);
1116         int sz_x = asInt(m_rtype, m_rvalue, node);
1117         it.Next()->Accept(*this);
1118         int sz_y = asInt(m_rtype, m_rvalue, node);
1119 
1120         mat->Resize(sz_x, sz_y);
1121         mat->RemoveReference();
1122       } else if (m_rtype.type == TYPE(ARRAY)) {
1123         cLocalArray* arr = m_rvalue.as_array;
1124 
1125         if (!arr->IsResizable()) INTERPRET_ERROR(CANNOT_RESIZE_MATRIX_ROW);
1126 
1127         if (args->GetSize() != 1) INTERPRET_ERROR(INVALID_ARRAY_SIZE);
1128 
1129         if (!arr->IsShared()) {
1130           arr->RemoveReference();
1131           break;
1132         }
1133 
1134         args->Iterator().Next()->Accept(*this);
1135         int sz = asInt(m_rtype, m_rvalue, node);
1136 
1137         arr->Resize(sz);
1138         arr->RemoveReference();
1139       } else {
1140         INTERPRET_ERROR(UNDEFINED_TYPE_OP, "resize", mapType(m_rtype));
1141       }
1142       break;
1143 
1144     default:
1145       INTERPRET_ERROR(INTERNAL);
1146       break;
1147   }
1148 }
1149 
1150 
VisitFunctionCall(cASTFunctionCall & node)1151 void cDirectInterpretASTVisitor::VisitFunctionCall(cASTFunctionCall& node)
1152 {
1153   if (node.IsASFunction()) {
1154     // Call internal function
1155     const cASFunction* func = node.GetASFunction();
1156 
1157     // Setup arguments
1158     cASCPPParameter* args = new cASCPPParameter[func->GetArity()];
1159     if (func->GetArity()) {
1160       tListIterator<cASTNode> cit = node.GetArguments()->Iterator();
1161       cASTNode* an = NULL;
1162       for (int i = 0; i < func->GetArity(); i++) {
1163         an = cit.Next();
1164         an->Accept(*this);
1165 
1166         switch (func->GetArgumentType(i).type) {
1167           case TYPE(BOOL):        args[i].Set(asBool(m_rtype, m_rvalue, node)); break;
1168           case TYPE(CHAR):        args[i].Set(asChar(m_rtype, m_rvalue, node)); break;
1169           case TYPE(FLOAT):       args[i].Set(asFloat(m_rtype, m_rvalue, node)); break;
1170           case TYPE(INT):         args[i].Set(asInt(m_rtype, m_rvalue, node)); break;
1171           case TYPE(STRING):      args[i].Set(asString(m_rtype, m_rvalue, node)); break;
1172           case TYPE(OBJECT_REF):  args[i].Set(asNativeObject(func->GetArgumentType(i).info, m_rtype, m_rvalue, node)); break;
1173 
1174           default:
1175             INTERPRET_ERROR(INTERNAL);
1176         }
1177       }
1178     }
1179 
1180     // Call the function
1181     cASCPPParameter rvalue = func->Call(args);
1182 
1183     // Handle the return value
1184     switch (node.GetType().type) {
1185       case TYPE(BOOL):        m_rvalue.as_bool = rvalue.Get<bool>(); break;
1186       case TYPE(CHAR):        m_rvalue.as_char = rvalue.Get<char>(); break;
1187       case TYPE(FLOAT):       m_rvalue.as_float = rvalue.Get<double>(); break;
1188       case TYPE(INT):         m_rvalue.as_int = rvalue.Get<int>(); break;
1189       case TYPE(STRING):      m_rvalue.as_string = rvalue.Get<cString*>(); break;
1190       case TYPE(OBJECT_REF):  m_rvalue.as_nobj = rvalue.Get<cASNativeObject*>(); break;
1191       case TYPE(VOID):        break;
1192 
1193       default:
1194         INTERPRET_ERROR(INTERNAL);
1195     }
1196     m_rtype = node.GetType();
1197 
1198     // Clean up arguments
1199     for (int i = 0; i < func->GetArity(); i++) {
1200       switch (func->GetArgumentType(i).type) {
1201         case TYPE(BOOL):    break;
1202         case TYPE(CHAR):    break;
1203         case TYPE(FLOAT):   break;
1204         case TYPE(INT):     break;
1205         case TYPE(STRING):  delete args[i].Get<cString*>(); break;
1206         case TYPE(OBJECT_REF):
1207           args[i].Get<cASNativeObject*>()->RemoveReference(); break;
1208 
1209         default:
1210           INTERPRET_ERROR(INTERNAL);
1211       }
1212     }
1213     delete [] args;
1214 
1215   } else {
1216     // Save previous scope information
1217     cSymbolTable* prev_symtbl = m_cur_symtbl;
1218 
1219     // Get function information
1220     cSymbolTable* func_src_symtbl = node.IsFuncGlobal() ? m_global_symtbl : m_cur_symtbl;
1221     int fun_id = node.GetFuncID();
1222 
1223     // Set current scope to the function symbol table
1224     cSymbolTable* func_symtbl = func_src_symtbl->GetFunctionSymbolTable(fun_id);
1225     int o_sp = m_sp;
1226     int sp = m_call_stack.GetSize();
1227     m_call_stack.Resize(m_call_stack.GetSize() + func_symtbl->GetNumVariables());
1228     for (int i = 0; i < func_symtbl->GetNumVariables(); i++) {
1229       switch (func_symtbl->GetVariableType(i).type) {
1230         case TYPE(ARRAY):       m_call_stack[sp + i].value.as_array = new cLocalArray; break;
1231         case TYPE(BOOL):        m_call_stack[sp + i].value.as_bool = false; break;
1232         case TYPE(CHAR):        m_call_stack[sp + i].value.as_char = 0; break;
1233         case TYPE(DICT):        m_call_stack[sp + i].value.as_dict = new cLocalDict; break;
1234         case TYPE(INT):         m_call_stack[sp + i].value.as_int = 0; break;
1235         case TYPE(FLOAT):       m_call_stack[sp + i].value.as_float = 0.0; break;
1236         case TYPE(MATRIX):      m_call_stack[sp + i].value.as_matrix = NULL; break;
1237         case TYPE(OBJECT_REF):  m_call_stack[sp + i].value.as_ref = NULL; break;
1238         case TYPE(STRING):      m_call_stack[sp + i].value.as_string = NULL; break;
1239         case TYPE(VAR):         m_call_stack[sp + i].type = TYPE(INVALID); break;
1240         default: break;
1241       }
1242     }
1243 
1244     // Process the arguments to the function
1245     tListIterator<cASTVariableDefinition> sit = func_src_symtbl->GetFunctionSignature(fun_id)->Iterator();
1246     tListIterator<cASTNode> cit = node.GetArguments()->Iterator();
1247     cASTVariableDefinition* arg_def = NULL;
1248     while ((arg_def = sit.Next())) {
1249       cASTNode* arg = cit.Next();
1250       if (arg) arg->Accept(*this);
1251       else arg_def->GetAssignmentExpression()->Accept(*this);
1252 
1253       int var_id = arg_def->GetVarID();
1254 
1255       switch (func_symtbl->GetVariableType(var_id).type) {
1256         case TYPE(ARRAY):       m_call_stack[sp + var_id].value.as_array = asArray(m_rtype, m_rvalue, node); break;
1257         case TYPE(BOOL):        m_call_stack[sp + var_id].value.as_bool = asBool(m_rtype, m_rvalue, node); break;
1258         case TYPE(CHAR):        m_call_stack[sp + var_id].value.as_char = asChar(m_rtype, m_rvalue, node); break;
1259         case TYPE(DICT):        m_call_stack[sp + var_id].value.as_dict = asDict(m_rtype, m_rvalue, node); break;
1260         case TYPE(FLOAT):       m_call_stack[sp + var_id].value.as_float = asFloat(m_rtype, m_rvalue, node); break;
1261         case TYPE(INT):         m_call_stack[sp + var_id].value.as_int = asInt(m_rtype, m_rvalue, node); break;
1262         case TYPE(OBJECT_REF):  m_call_stack[sp + var_id].value.as_nobj = asNativeObject(func_symtbl->GetVariableType(var_id).info, m_rtype, m_rvalue, node); break;
1263         case TYPE(MATRIX):      m_call_stack[sp + var_id].value.as_matrix = asMatrix(m_rtype, m_rvalue, node); break;
1264         case TYPE(STRING):
1265           {
1266             m_call_stack[sp + var_id].value.as_string = asString(m_rtype, m_rvalue, node);
1267           }
1268           break;
1269 
1270         case TYPE(VAR):
1271           m_call_stack[sp + var_id].value = m_rvalue;
1272           m_call_stack[sp + var_id].type = m_rtype;
1273           break;
1274 
1275         default:
1276           INTERPRET_ERROR(INTERNAL);
1277       }
1278     }
1279 
1280 
1281     // Execute the function
1282     m_cur_symtbl = func_symtbl;
1283     m_sp = sp;
1284     func_src_symtbl->GetFunctionDefinition(fun_id)->Accept(*this);
1285 
1286     // Handle function return value
1287     switch (node.GetType().type) {
1288       case TYPE(ARRAY):       m_rvalue.as_array = asArray(m_rtype, m_rvalue, node); break;
1289       case TYPE(BOOL):        m_rvalue.as_bool = asBool(m_rtype, m_rvalue, node); break;
1290       case TYPE(CHAR):        m_rvalue.as_char = asChar(m_rtype, m_rvalue, node); break;
1291       case TYPE(DICT):        m_rvalue.as_dict = asDict(m_rtype, m_rvalue, node); break;
1292       case TYPE(FLOAT):       m_rvalue.as_float = asFloat(m_rtype, m_rvalue, node); break;
1293       case TYPE(INT):         m_rvalue.as_int = asInt(m_rtype, m_rvalue, node); break;
1294       case TYPE(OBJECT_REF):  m_rvalue.as_nobj = asNativeObject(node.GetType().info, m_rtype, m_rvalue, node); break;
1295       case TYPE(MATRIX):      m_rvalue.as_matrix = asMatrix(m_rtype, m_rvalue, node); break;
1296       case TYPE(STRING):      m_rvalue.as_string = asString(m_rtype, m_rvalue, node); break;
1297       case TYPE(VAR):         break;
1298       case TYPE(VOID):        break;
1299 
1300       default:
1301         INTERPRET_ERROR(INTERNAL);
1302     }
1303     if (node.GetType() != TYPE(VAR)) m_rtype = node.GetType();
1304 
1305     // Clean up variables in the current scope
1306     for (int i = 0; i < func_symtbl->GetNumVariables(); i++) {
1307       ASType_t type = func_symtbl->GetVariableType(i).type;
1308       if (type == TYPE(VAR)) type = m_call_stack[sp + i].type.type;
1309 
1310       switch (type) {
1311         case TYPE(ARRAY):       m_call_stack[sp + i].value.as_array->RemoveReference(); break;
1312         case TYPE(DICT):        m_call_stack[sp + i].value.as_dict->RemoveReference(); break;
1313         case TYPE(MATRIX):      m_call_stack[sp + i].value.as_matrix->RemoveReference(); break;
1314         case TYPE(OBJECT_REF):  delete m_call_stack[sp + i].value.as_ref; break;
1315         case TYPE(STRING):      delete m_call_stack[sp + i].value.as_string; break;
1316         default: break;
1317       }
1318     }
1319 
1320     // Restore previous scope
1321     m_has_returned = false;
1322     m_call_stack.Resize(m_call_stack.GetSize() - m_cur_symtbl->GetNumVariables());
1323     m_sp = o_sp;
1324     m_cur_symtbl = prev_symtbl;
1325   }
1326 }
1327 
1328 
VisitLiteral(cASTLiteral & node)1329 void cDirectInterpretASTVisitor::VisitLiteral(cASTLiteral& node)
1330 {
1331   switch (node.GetType().type) {
1332     case TYPE(BOOL):
1333       if (node.GetValue() == "true") m_rvalue.as_bool = true;
1334       else m_rvalue.as_bool = false;
1335       m_rtype = TYPE(BOOL);
1336       break;
1337     case TYPE(CHAR):
1338       m_rvalue.as_char = node.GetValue()[0];
1339       m_rtype = TYPE(CHAR);
1340       break;
1341       case TYPE(INT):
1342       m_rvalue.as_int = node.GetValue().AsInt();
1343       m_rtype = TYPE(INT);
1344       break;
1345     case TYPE(FLOAT):
1346       m_rvalue.as_float = node.GetValue().AsDouble();
1347       m_rtype = TYPE(FLOAT);
1348       break;
1349     case TYPE(STRING):
1350       m_rvalue.as_string = new cString(node.GetValue());
1351       m_rtype = TYPE(STRING);
1352       break;
1353     default:
1354       INTERPRET_ERROR(INTERNAL);
1355   }
1356 }
1357 
1358 
VisitLiteralArray(cASTLiteralArray & node)1359 void cDirectInterpretASTVisitor::VisitLiteralArray(cASTLiteralArray& node)
1360 {
1361   cASTArgumentList* vals = node.GetValues();
1362 
1363   if (node.IsMatrix()) {
1364     cLocalMatrix* mat = new cLocalMatrix();
1365 
1366     int sz_y = 1;
1367     bool first = true;
1368 
1369     tListIterator<cASTNode> it = vals->Iterator();
1370     cASTNode* val = NULL;
1371     int i = 0;
1372     while ((val = it.Next())) {
1373       val->Accept(*this);
1374       if (first && m_rtype.type == TYPE(ARRAY)) {
1375         sz_y = m_rvalue.as_array->GetSize();
1376       }
1377 
1378       mat->Resize(i + 1, sz_y);
1379 
1380       if (sz_y > 1) {
1381         if (m_rtype.type != TYPE(ARRAY)) INTERPRET_ERROR(INVALID_ARRAY_SIZE);
1382         mat->Set(i, m_rvalue.as_array);
1383       } else {
1384         mat->GetRow(i)->Set(0, m_rtype, m_rvalue);
1385       }
1386 
1387       sAggregateValue val(m_rtype, m_rvalue);
1388       val.Cleanup();
1389       first = false;
1390       i++;
1391     }
1392 
1393     m_rvalue.as_matrix = mat;
1394     m_rtype = TYPE(MATRIX);
1395   } else {
1396     cLocalArray* arr = new cLocalArray(vals->GetSize());
1397 
1398     tListIterator<cASTNode> it = vals->Iterator();
1399     cASTNode* val = NULL;
1400     int i = 0;
1401     while ((val = it.Next())) {
1402       val->Accept(*this);
1403       arr->Set(i++, m_rtype.type, m_rvalue);
1404     }
1405 
1406     m_rvalue.as_array = arr;
1407     m_rtype = TYPE(ARRAY);
1408   }
1409 }
1410 
VisitLiteralDict(cASTLiteralDict & node)1411 void cDirectInterpretASTVisitor::VisitLiteralDict(cASTLiteralDict& node)
1412 {
1413   cLocalDict* dict = new cLocalDict();
1414 
1415   sAggregateValue idx,val;
1416   tListIterator<cASTLiteralDict::sMapping> it(node.Iterator());
1417   cASTLiteralDict::sMapping* mapping = NULL;
1418   while ((mapping = it.Next())) {
1419     mapping->idx->Accept(*this);
1420     idx.type = m_rtype;
1421     idx.value = m_rvalue;
1422     mapping->val->Accept(*this);
1423     val.type = m_rtype;
1424     val.value = m_rvalue;
1425     dict->Set(idx, val);
1426   }
1427 
1428   m_rvalue.as_dict = dict;
1429   m_rtype = TYPE(DICT);
1430 }
1431 
VisitObjectCall(cASTObjectCall & node)1432 void cDirectInterpretASTVisitor::VisitObjectCall(cASTObjectCall& node)
1433 {
1434   node.GetObject()->Accept(*this);
1435 
1436   if (m_rtype.type != TYPE(OBJECT_REF))
1437     INTERPRET_ERROR(TYPE_CAST, mapType(m_rtype.type), mapType(TYPE(OBJECT_REF)));
1438 
1439   cASNativeObject* nobj = m_rvalue.as_nobj;
1440 
1441   int mid = -1;
1442   if (!nobj->LookupMethod(node.GetName(), mid))
1443     INTERPRET_ERROR(NOBJ_METHOD_LOOKUP_FAILED, *node.GetName(), *m_rtype.info);
1444 
1445   int arity = nobj->GetArity(mid);
1446   // Setup arguments
1447   cASCPPParameter* args = new cASCPPParameter[arity];
1448   if (arity) {
1449     tListIterator<cASTNode> cit = node.GetArguments()->Iterator();
1450     cASTNode* an = NULL;
1451     for (int i = 0; i < arity; i++) {
1452       an = cit.Next();
1453       an->Accept(*this);
1454 
1455       switch (nobj->GetArgumentType(mid, i).type) {
1456         case TYPE(BOOL):        args[i].Set(asBool(m_rtype, m_rvalue, node)); break;
1457         case TYPE(CHAR):        args[i].Set(asChar(m_rtype, m_rvalue, node)); break;
1458         case TYPE(FLOAT):       args[i].Set(asFloat(m_rtype, m_rvalue, node)); break;
1459         case TYPE(INT):         args[i].Set(asInt(m_rtype, m_rvalue, node)); break;
1460         case TYPE(STRING):      args[i].Set(asString(m_rtype, m_rvalue, node)); break;
1461 
1462         default:
1463           INTERPRET_ERROR(INTERNAL);
1464       }
1465     }
1466   }
1467 
1468   // Call the function
1469   cASCPPParameter rvalue = nobj->CallMethod(mid, args);
1470 
1471   // Handle the return value
1472   m_rtype = nobj->GetReturnType(mid);
1473   switch (m_rtype.type) {
1474     case TYPE(BOOL):        m_rvalue.as_bool = rvalue.Get<bool>(); break;
1475     case TYPE(CHAR):        m_rvalue.as_char = rvalue.Get<char>(); break;
1476     case TYPE(FLOAT):       m_rvalue.as_float = rvalue.Get<double>(); break;
1477     case TYPE(INT):         m_rvalue.as_int = rvalue.Get<int>(); break;
1478     case TYPE(STRING):      m_rvalue.as_string = rvalue.Get<cString*>(); break;
1479     case TYPE(OBJECT_REF):  m_rvalue.as_nobj = rvalue.Get<cASNativeObject*>(); break;
1480     case TYPE(VOID):        break;
1481 
1482     default:
1483       INTERPRET_ERROR(INTERNAL);
1484   }
1485 
1486   // Clean up arguments
1487   for (int i = 0; i < arity; i++) {
1488     switch (nobj->GetArgumentType(mid, i).type) {
1489       case TYPE(BOOL):    break;
1490       case TYPE(CHAR):    break;
1491       case TYPE(FLOAT):   break;
1492       case TYPE(INT):     break;
1493       case TYPE(STRING):  delete args[i].Get<cString*>(); break;
1494 
1495       default:
1496         INTERPRET_ERROR(INTERNAL);
1497     }
1498   }
1499   delete [] args;
1500 
1501 }
1502 
VisitObjectReference(cASTObjectReference & node)1503 void cDirectInterpretASTVisitor::VisitObjectReference(cASTObjectReference& node)
1504 {
1505   // @AS_TODO - handle object reference
1506   INTERPRET_ERROR(INTERNAL);
1507 }
1508 
VisitVariableReference(cASTVariableReference & node)1509 void cDirectInterpretASTVisitor::VisitVariableReference(cASTVariableReference& node)
1510 {
1511   int var_id = node.GetVarID();
1512   int sp = node.IsVarGlobal() ? 0 : m_sp;
1513 
1514   if (m_obj_assign) {
1515     switch (node.GetType().type) {
1516       case TYPE(ARRAY):       m_rvalue.as_ref = new cArrayVarRef(m_call_stack[sp + var_id].value); break;
1517       case TYPE(DICT):        m_rvalue.as_ref = new cDictVarRef(m_call_stack[sp + var_id].value); break;
1518       case TYPE(OBJECT_REF):  m_rvalue.as_ref = new cNativeObjectVarRef(m_call_stack[sp + var_id].value); break;
1519       case TYPE(MATRIX):      m_rvalue.as_ref = new cMatrixVarRef(m_call_stack[sp + var_id].value); break;
1520       case TYPE(STRING):      m_rvalue.as_ref = new cStringVarRef(m_call_stack[sp + var_id].value); break;
1521 
1522       default:
1523         INTERPRET_ERROR(INTERNAL);
1524     }
1525     m_rtype = TYPE(OBJECT_REF);
1526   } else {
1527     ASType_t type = node.GetType().type;
1528     if (type == TYPE(VAR)) type = m_call_stack[sp + var_id].type.type;
1529 
1530     m_rtype = sASTypeInfo(type);
1531 
1532     switch (type) {
1533       case TYPE(ARRAY):       m_rvalue.as_array = m_call_stack[sp + var_id].value.as_array->GetReference(); break;
1534       case TYPE(BOOL):        m_rvalue.as_bool = m_call_stack[sp + var_id].value.as_bool; break;
1535       case TYPE(CHAR):        m_rvalue.as_char = m_call_stack[sp + var_id].value.as_char; break;
1536       case TYPE(DICT):        m_rvalue.as_dict = m_call_stack[sp + var_id].value.as_dict->GetReference(); break;
1537       case TYPE(FLOAT):       m_rvalue.as_float = m_call_stack[sp + var_id].value.as_float; break;
1538       case TYPE(INT):         m_rvalue.as_int = m_call_stack[sp + var_id].value.as_int; break;
1539       case TYPE(MATRIX):      m_rvalue.as_matrix = m_call_stack[sp + var_id].value.as_matrix->GetReference(); break;
1540       case TYPE(STRING):      m_rvalue.as_string = new cString(*m_call_stack[sp + var_id].value.as_string); break;
1541 
1542 
1543       case TYPE(OBJECT_REF):
1544         m_rvalue.as_nobj = m_call_stack[sp + var_id].value.as_nobj->GetReference();
1545         m_rtype.info = m_call_stack[sp + var_id].type.info;
1546         break;
1547 
1548       default:
1549         INTERPRET_ERROR(INTERNAL);
1550     }
1551   }
1552 }
1553 
1554 
VisitUnpackTarget(cASTUnpackTarget & node)1555 void cDirectInterpretASTVisitor::VisitUnpackTarget(cASTUnpackTarget& node)
1556 {
1557   node.GetExpression()->Accept(*this);
1558   cLocalArray* arr = m_rvalue.as_array;
1559 
1560   int unpack_size = node.GetSize();
1561   if (node.IsLastNamed()) unpack_size--;
1562   if (unpack_size > arr->GetSize()) INTERPRET_ERROR(UNPACK_VALUE_TOO_SMALL);
1563   if (unpack_size < arr->GetSize() && !node.IsLastWild()) INTERPRET_ERROR(UNPACK_VALUE_TOO_LARGE);
1564 
1565   // Unpack the values up to the last non-wild value
1566   for (int i = 0; i < unpack_size; i++) {
1567     sASTypeInfo var_type = (node.IsVarGlobal(i) ? m_global_symtbl : m_cur_symtbl)->GetVariableType(node.GetVarID(i));
1568     int var_idx = (node.IsVarGlobal(i) ? 0 : m_sp) + node.GetVarID(i);
1569 
1570     // Set the variable value for this iteration
1571     const sAggregateValue& val = arr->Get(i);
1572     switch (var_type.type) {
1573       case TYPE(BOOL):        m_call_stack[var_idx].value.as_bool = asBool(val.type, val.value, node); break;
1574       case TYPE(CHAR):        m_call_stack[var_idx].value.as_char = asChar(val.type, val.value, node); break;
1575       case TYPE(FLOAT):       m_call_stack[var_idx].value.as_float = asFloat(val.type, val.value, node); break;
1576       case TYPE(INT):         m_call_stack[var_idx].value.as_int = asInt(val.type, val.value, node); break;
1577       case TYPE(OBJECT_REF):
1578         m_call_stack[var_idx].value.as_nobj->RemoveReference();
1579         m_call_stack[var_idx].value.as_nobj = asNativeObject(var_type.info, val.type, val.value, node);
1580         break;
1581 
1582       case TYPE(VAR):
1583         m_call_stack[var_idx].value = val.value;
1584         m_call_stack[var_idx].type = val.type;
1585         break;
1586 
1587       case TYPE(ARRAY):
1588         m_call_stack[var_idx].value.as_array->RemoveReference();
1589         m_call_stack[var_idx].value.as_array = asArray(val.type, val.value, node);
1590         break;
1591 
1592       case TYPE(DICT):
1593         m_call_stack[var_idx].value.as_dict->RemoveReference();
1594         m_call_stack[var_idx].value.as_dict = asDict(val.type, val.value, node);
1595         break;
1596 
1597       case TYPE(MATRIX):
1598         m_call_stack[var_idx].value.as_matrix->RemoveReference();
1599         m_call_stack[var_idx].value.as_matrix = asMatrix(val.type, val.value, node);
1600         break;
1601 
1602       case TYPE(STRING):
1603         delete m_call_stack[var_idx].value.as_string;
1604         m_call_stack[var_idx].value.as_string = asString(val.type, val.value, node);
1605         break;
1606 
1607       default:
1608         INTERPRET_ERROR(INTERNAL);
1609     }
1610   }
1611 
1612   if (node.IsLastNamed()) {
1613     int var_idx = (node.IsVarGlobal(unpack_size) ? 0 : m_sp) + node.GetVarID(unpack_size);
1614     int sz = arr->GetSize() - unpack_size;
1615 
1616     cLocalArray* wild = new cLocalArray(sz);
1617 
1618     for (int i = 0; i < sz; i++) {
1619       const sAggregateValue& val = arr->Get(i + unpack_size);
1620       wild->Set(i, val.type, val.value);
1621     }
1622 
1623     m_call_stack[var_idx].value.as_array->RemoveReference();
1624     m_call_stack[var_idx].value.as_array = wild;
1625   }
1626 
1627   arr->RemoveReference();
1628 }
1629 
asArray(const sASTypeInfo & type,uAnyType value,cASTNode & node)1630 cDirectInterpretASTVisitor::cLocalArray* cDirectInterpretASTVisitor::asArray(const sASTypeInfo& type, uAnyType value, cASTNode& node)
1631 {
1632   switch (type.type) {
1633     case TYPE(ARRAY):
1634       return value.as_array;
1635 
1636     case TYPE(MATRIX):
1637       {
1638         cLocalMatrix* mat = value.as_matrix;
1639         cLocalArray* arr = new cLocalArray(mat->GetNumRows());
1640         uAnyType val;
1641         for (int i = 0; i < mat->GetNumRows(); i++) {
1642           val.as_array = new cLocalArray(mat->GetRow(i));
1643           arr->Set(i, TYPE(ARRAY), val);
1644         }
1645         mat->RemoveReference();
1646         return arr;
1647       }
1648 
1649     case TYPE(STRING):
1650       {
1651         cString* str = value.as_string;
1652         cLocalArray* arr = new cLocalArray(str->GetSize());
1653         for (int i = 0; i < str->GetSize(); i++) {
1654           uAnyType val;
1655           val.as_char = (*str)[i];
1656           arr->Set(i, TYPE(CHAR), val);
1657         }
1658         delete str;
1659         return arr;
1660       }
1661 
1662     default:
1663       INTERPRET_ERROR(TYPE_CAST, mapType(type), mapType(TYPE(ARRAY)));
1664   }
1665 
1666   return false;
1667 }
1668 
asBool(const sASTypeInfo & type,uAnyType value,cASTNode & node)1669 bool cDirectInterpretASTVisitor::asBool(const sASTypeInfo& type, uAnyType value, cASTNode& node)
1670 {
1671   switch (type.type) {
1672     case TYPE(ARRAY):
1673       {
1674         bool rval = (value.as_array->GetSize());
1675         value.as_array->RemoveReference();
1676         return rval;
1677       }
1678 
1679     case TYPE(DICT):
1680     {
1681       bool rval = (value.as_dict->GetSize());
1682       value.as_dict->RemoveReference();
1683       return rval;
1684     }
1685 
1686     case TYPE(MATRIX):
1687       {
1688         bool rval = (value.as_matrix->GetNumRows() && value.as_matrix->GetNumCols());
1689         value.as_matrix->RemoveReference();
1690         return rval;
1691       }
1692 
1693     case TYPE(BOOL):
1694       return value.as_bool;
1695     case TYPE(CHAR):
1696       return (value.as_char);
1697     case TYPE(FLOAT):
1698       return (value.as_float != 0);
1699     case TYPE(INT):
1700       return (value.as_int);
1701     case TYPE(STRING):
1702       {
1703         bool rval = (*value.as_string != "");
1704         delete value.as_string;
1705         return rval;
1706       }
1707 
1708 
1709     case TYPE(OBJECT_REF): // @AS_TODO - implement asBool
1710       INTERPRET_ERROR(INTERNAL);
1711 
1712     default:
1713       INTERPRET_ERROR(TYPE_CAST, mapType(type), mapType(TYPE(BOOL)));
1714   }
1715 
1716   return false;
1717 }
1718 
1719 
asChar(const sASTypeInfo & type,uAnyType value,cASTNode & node)1720 char cDirectInterpretASTVisitor::asChar(const sASTypeInfo& type, uAnyType value, cASTNode& node)
1721 {
1722   switch (type.type) {
1723     case TYPE(BOOL):
1724       return (value.as_bool) ? 1 : 0;
1725     case TYPE(CHAR):
1726       return value.as_char;
1727     case TYPE(INT):
1728       return (char)value.as_int;
1729 
1730     default:
1731       INTERPRET_ERROR(TYPE_CAST, mapType(type), mapType(TYPE(CHAR)));
1732   }
1733 
1734   return 0;
1735 }
1736 
1737 
asDict(const sASTypeInfo & type,uAnyType value,cASTNode & node)1738 cDirectInterpretASTVisitor::cLocalDict* cDirectInterpretASTVisitor::asDict(const sASTypeInfo& type, uAnyType value,
1739                                                                            cASTNode& node)
1740 {
1741   switch (type.type) {
1742     case TYPE(DICT):
1743       return value.as_dict;
1744 
1745     case TYPE(ARRAY):
1746       {
1747         cLocalDict* dict = new cLocalDict();
1748         cLocalArray* arr = value.as_array;
1749 
1750         sAggregateValue idx;
1751         idx.type.type = TYPE(INT);
1752 
1753         for (idx.value.as_int = 0; idx.value.as_int < arr->GetSize(); idx.value.as_int++) {
1754           dict->Set(idx, arr->Get(idx.value.as_int));
1755         }
1756 
1757         arr->RemoveReference();
1758         return dict;
1759       }
1760 
1761     default:
1762       INTERPRET_ERROR(TYPE_CAST, mapType(type), mapType(TYPE(CHAR)));
1763   }
1764 
1765   return false;
1766 }
1767 
asInt(const sASTypeInfo & type,uAnyType value,cASTNode & node)1768 int cDirectInterpretASTVisitor::asInt(const sASTypeInfo& type, uAnyType value, cASTNode& node)
1769 {
1770   switch (type.type) {
1771     case TYPE(BOOL):
1772       return (value.as_bool) ? 1 : 0;
1773     case TYPE(CHAR):
1774       return (int)value.as_char;
1775     case TYPE(INT):
1776       return value.as_int;
1777     case TYPE(FLOAT):
1778       return (int)value.as_float;
1779     case TYPE(STRING):
1780       {
1781         int rval = value.as_string->AsInt();
1782         delete value.as_string;
1783         return rval;
1784       }
1785 
1786     default:
1787       INTERPRET_ERROR(TYPE_CAST, mapType(type), mapType(TYPE(INT)));
1788   }
1789 
1790   return 0;
1791 }
1792 
1793 
asFloat(const sASTypeInfo & type,uAnyType value,cASTNode & node)1794 double cDirectInterpretASTVisitor::asFloat(const sASTypeInfo& type, uAnyType value, cASTNode& node)
1795 {
1796   switch (type.type) {
1797     case TYPE(BOOL):
1798       return (value.as_bool) ? 1.0 : 0.0;
1799     case TYPE(CHAR):
1800       return (double)value.as_char;
1801     case TYPE(INT):
1802       return (double)value.as_int;
1803     case TYPE(FLOAT):
1804       return value.as_float;
1805     case TYPE(STRING):
1806       {
1807         double rval = value.as_string->AsDouble();
1808         delete value.as_string;
1809         return rval;
1810       }
1811 
1812     default:
1813       INTERPRET_ERROR(TYPE_CAST, mapType(type), mapType(TYPE(FLOAT)));
1814   }
1815 
1816   return 0.0;
1817 }
1818 
1819 
asMatrix(const sASTypeInfo & type,uAnyType value,cASTNode & node)1820 cDirectInterpretASTVisitor::cLocalMatrix* cDirectInterpretASTVisitor::asMatrix(const sASTypeInfo& type, uAnyType value,
1821                                                                                cASTNode& node)
1822 {
1823   switch (type.type) {
1824     case TYPE(BOOL):
1825     case TYPE(CHAR):
1826     case TYPE(FLOAT):
1827     case TYPE(INT):
1828       {
1829         sAggregateValue val(type, value);
1830         cLocalMatrix* mat = new cLocalMatrix();
1831         mat->Resize(1, 1);
1832         mat->GetRow(0)->Set(0, val);
1833         return mat;
1834       }
1835 
1836     case TYPE(MATRIX):
1837       return value.as_matrix;
1838 
1839     default:
1840       INTERPRET_ERROR(TYPE_CAST, mapType(type), mapType(TYPE(MATRIX)));
1841   }
1842 
1843   return NULL;
1844 }
1845 
1846 
asNativeObject(const cString & info,const sASTypeInfo & type,uAnyType value,cASTNode & node)1847 cASNativeObject* cDirectInterpretASTVisitor::asNativeObject(const cString& info, const sASTypeInfo& type, uAnyType value,
1848                                                             cASTNode& node)
1849 {
1850   switch (type.type) {
1851     case TYPE(OBJECT_REF):
1852       if (type.info != info) INTERPRET_ERROR(NOBJ_TYPE_MISMATCH, *info, *type.info);
1853       return value.as_nobj;
1854 
1855     default:
1856       INTERPRET_ERROR(TYPE_CAST, mapType(type), mapType(TYPE(OBJECT_REF)));
1857   }
1858 
1859   return NULL;
1860 }
1861 
1862 
asString(const sASTypeInfo & type,uAnyType value,cASTNode & node)1863 cString* cDirectInterpretASTVisitor::asString(const sASTypeInfo& type, uAnyType value, cASTNode& node)
1864 {
1865   switch (type.type) {
1866     case TYPE(BOOL):        return new cString(cStringUtil::Convert(value.as_bool));
1867     case TYPE(CHAR):        { cString* str = new cString(1); (*str)[0] = value.as_char; return str; }
1868     case TYPE(INT):         return new cString(cStringUtil::Convert(value.as_int));
1869     case TYPE(FLOAT):       return new cString(cStringUtil::Convert(value.as_float));
1870     case TYPE(STRING):      return value.as_string;
1871 
1872     case TYPE(ARRAY):
1873       {
1874         cString* str = new cString(cStringUtil::Stringf("< array(%d) >", value.as_array->GetSize()));
1875         value.as_array->RemoveReference();
1876         return str;
1877       }
1878 
1879     case TYPE(DICT):
1880     {
1881       cString* str = new cString(cStringUtil::Stringf("< dict(%d) >", value.as_dict->GetSize()));
1882       value.as_dict->RemoveReference();
1883       return str;
1884     }
1885 
1886     case TYPE(MATRIX):
1887       {
1888         cString* str = new cString(cStringUtil::Stringf("< matrix(%d, %d) >", value.as_matrix->GetNumRows(), value.as_matrix->GetNumCols()));
1889         return str;
1890       }
1891 
1892     case TYPE(OBJECT_REF):
1893     {
1894       cString* str = new cString(cStringUtil::Stringf("< %s object @ %p >", value.as_nobj->GetType(), value.as_nobj));
1895       return str;
1896     }
1897 
1898     default:
1899       INTERPRET_ERROR(TYPE_CAST, mapType(type), mapType(TYPE(STRING)));
1900   }
1901 
1902   return NULL;
1903 }
1904 
1905 
1906 
getRuntimeType(ASType_t ltype,ASType_t rtype,bool allow_str)1907 ASType_t cDirectInterpretASTVisitor::getRuntimeType(ASType_t ltype, ASType_t rtype, bool allow_str)
1908 {
1909   switch (ltype) {
1910     case TYPE(ARRAY):
1911       return TYPE(ARRAY);
1912     case TYPE(BOOL):
1913       switch (rtype) {
1914         case TYPE(ARRAY):
1915         case TYPE(BOOL):
1916         case TYPE(CHAR):
1917         case TYPE(FLOAT):
1918         case TYPE(INT):
1919         case TYPE(MATRIX):
1920         case TYPE(OBJECT_REF):
1921         case TYPE(STRING):
1922           return TYPE(BOOL);
1923 
1924         default: break;
1925       }
1926       break;
1927     case TYPE(CHAR):
1928       switch (rtype) {
1929         case TYPE(ARRAY):     return TYPE(ARRAY);
1930         case TYPE(BOOL):      return TYPE(CHAR);
1931         case TYPE(CHAR):      return TYPE(CHAR);
1932         case TYPE(FLOAT):     return TYPE(FLOAT);
1933         case TYPE(INT):       return TYPE(INT);
1934         case TYPE(MATRIX):    return TYPE(MATRIX);
1935         case TYPE(STRING):    if (allow_str) return TYPE(STRING); break;
1936         default: break;
1937       }
1938       break;
1939     case TYPE(DICT):
1940       return TYPE(DICT);
1941     case TYPE(FLOAT):
1942       switch (rtype) {
1943         case TYPE(ARRAY):     return TYPE(ARRAY);
1944         case TYPE(BOOL):      return TYPE(FLOAT);
1945         case TYPE(CHAR):      return TYPE(FLOAT);
1946         case TYPE(FLOAT):     return TYPE(FLOAT);
1947         case TYPE(INT):       return TYPE(FLOAT);
1948         case TYPE(MATRIX):    return TYPE(MATRIX);
1949         case TYPE(STRING):    if (allow_str) return TYPE(FLOAT); break;
1950         default: break;
1951       }
1952       break;
1953     case TYPE(INT):
1954       switch (rtype) {
1955         case TYPE(ARRAY):     return TYPE(ARRAY);
1956         case TYPE(BOOL):      return TYPE(INT);
1957         case TYPE(CHAR):      return TYPE(INT);
1958         case TYPE(FLOAT):     return TYPE(FLOAT);
1959         case TYPE(INT):       return TYPE(INT);
1960         case TYPE(MATRIX):    return TYPE(MATRIX);
1961         case TYPE(STRING):    if (allow_str) return TYPE(INT); break;
1962         default: break;
1963       }
1964       break;
1965     case TYPE(MATRIX):
1966       return TYPE(MATRIX);
1967     case TYPE(STRING):
1968       if (allow_str) return TYPE(STRING); break;
1969 
1970     default: break;
1971   }
1972 
1973   return TYPE(INVALID);
1974 }
1975 
1976 
matrixAdd(cLocalMatrix * m1,cLocalMatrix * m2,cASTNode & node)1977 void cDirectInterpretASTVisitor::matrixAdd(cLocalMatrix* m1, cLocalMatrix* m2, cASTNode& node)
1978 {
1979   INTERPRET_ERROR(INTERNAL); // @AS_TODO - handle matrix add
1980 }
1981 
1982 
matrixSubtract(cLocalMatrix * m1,cLocalMatrix * m2,cASTNode & node)1983 void cDirectInterpretASTVisitor::matrixSubtract(cLocalMatrix* m1, cLocalMatrix* m2, cASTNode& node)
1984 {
1985   INTERPRET_ERROR(INTERNAL); // @AS_TODO - handle matrix sub
1986 }
1987 
1988 
matrixMultiply(cLocalMatrix * m1,cLocalMatrix * m2,cASTNode & node)1989 void cDirectInterpretASTVisitor::matrixMultiply(cLocalMatrix* m1, cLocalMatrix* m2, cASTNode& node)
1990 {
1991   // Validate all values in matrix operands and determine operation type
1992   ASType_t op_type = TYPE(INT);
1993   for (int i = 0; i < m1->GetNumRows(); i++) {
1994     cLocalArray* row = m1->GetRow(i);
1995     for (int j = 0; j < m1->GetNumCols(); j++) {
1996       switch (row->Get(j).type.type) {
1997         case TYPE(BOOL):
1998         case TYPE(CHAR):
1999         case TYPE(INT):
2000         case TYPE(STRING):
2001           break;
2002 
2003         case TYPE(FLOAT):
2004           op_type = TYPE(FLOAT);
2005           break;
2006 
2007         default:
2008           INTERPRET_ERROR(MATRIX_OP_TYPE_MISMATCH, mapToken(TOKEN(OP_MUL)), mapType(row->Get(j).type));
2009       }
2010     }
2011   }
2012   for (int i = 0; i < m2->GetNumRows(); i++) {
2013     cLocalArray* row = m2->GetRow(i);
2014     for (int j = 0; j < m2->GetNumCols(); j++) {
2015       switch (row->Get(j).type.type) {
2016         case TYPE(BOOL):
2017         case TYPE(CHAR):
2018         case TYPE(INT):
2019         case TYPE(STRING):
2020           break;
2021 
2022         case TYPE(FLOAT):
2023           op_type = TYPE(FLOAT);
2024           break;
2025 
2026         default:
2027           INTERPRET_ERROR(MATRIX_OP_TYPE_MISMATCH, mapToken(TOKEN(OP_MUL)), mapType(row->Get(j).type));
2028       }
2029     }
2030   }
2031 
2032 
2033 
2034   if (m1->GetNumRows() == 1 && m1->GetNumCols() == 1) {
2035     // left op scalar multiply
2036 
2037     if (op_type == TYPE(INT)) matrixMultiply_ScalarInt(m1, m2, node);
2038     else matrixMultiply_ScalarFloat(m1, m2, node);
2039 
2040   } else if (m2->GetNumRows() == 1 && m2->GetNumCols() == 1) {
2041     // right op scalar multiply
2042 
2043     if (op_type == TYPE(INT)) matrixMultiply_ScalarInt(m2, m1, node);
2044     else matrixMultiply_ScalarFloat(m2, m1, node);
2045 
2046   } else {
2047     // full multiply
2048 
2049     if (m1->GetNumCols() != m2->GetNumRows()) INTERPRET_ERROR(MATRIX_SIZE_MISMATCH, mapToken(TOKEN(OP_MUL)));
2050 
2051     if (op_type == TYPE(INT)) matrixMultiply_FullInt(m1, m2, node);
2052     else matrixMultiply_FullFloat(m1, m2, node);
2053   }
2054 }
2055 
matrixMultiply_ScalarInt(cLocalMatrix * s,cLocalMatrix * m,cASTNode & node)2056 void cDirectInterpretASTVisitor::matrixMultiply_ScalarInt(cLocalMatrix* s, cLocalMatrix* m, cASTNode& node)
2057 {
2058   int scalar = 0;
2059   tMatrix<int> op(m->GetNumRows(), m->GetNumCols());
2060 
2061   const sAggregateValue& val = s->GetRow(0)->Get(0);
2062   switch (val.type.type) {
2063     case TYPE(BOOL):    scalar = (val.value.as_bool) ? 1 : 0; break;
2064     case TYPE(CHAR):    scalar = (int)val.value.as_char; break;
2065     case TYPE(INT):     scalar = val.value.as_int; break;
2066     case TYPE(STRING):  scalar = val.value.as_string->AsInt(); break;
2067 
2068     default:
2069       INTERPRET_ERROR(MATRIX_OP_TYPE_MISMATCH, mapToken(TOKEN(OP_MUL)), mapType(val.type));
2070   }
2071 
2072   for (int i = 0; i < m->GetNumRows(); i++) {
2073     cLocalArray* row = m->GetRow(i);
2074     for (int j = 0; j < m->GetNumCols(); j++) {
2075       const sAggregateValue& val = row->Get(j);
2076       switch (val.type.type) {
2077         case TYPE(BOOL):    op[i][j] = (val.value.as_bool) ? 1 : 0; break;
2078         case TYPE(CHAR):    op[i][j] = (int)val.value.as_char; break;
2079         case TYPE(INT):     op[i][j] = val.value.as_int; break;
2080         case TYPE(STRING):  op[i][j] = val.value.as_string->AsInt(); break;
2081 
2082         default:
2083           INTERPRET_ERROR(MATRIX_OP_TYPE_MISMATCH, mapToken(TOKEN(OP_MUL)), mapType(row->Get(j).type));
2084       }
2085     }
2086   }
2087 
2088   int sz_x = m->GetNumRows();
2089   int sz_y = m->GetNumCols();
2090   cLocalMatrix* mat = new cLocalMatrix();
2091   mat->Resize(sz_x, sz_y);
2092 
2093   sASTypeInfo op_type(TYPE(INT));
2094   for (int i = 0; i < sz_x; i++) {
2095     cLocalArray* row = mat->GetRow(i);
2096     for (int j = 0; j < sz_y; j++) {
2097       uAnyType val;
2098       val.as_int = scalar * op[i][j];
2099       row->Set(j, op_type, val);
2100     }
2101   }
2102 
2103   m_rvalue.as_matrix = mat;
2104   m_rtype = TYPE(MATRIX);
2105 }
2106 
matrixMultiply_ScalarFloat(cLocalMatrix * s,cLocalMatrix * m,cASTNode & node)2107 void cDirectInterpretASTVisitor::matrixMultiply_ScalarFloat(cLocalMatrix* s, cLocalMatrix* m, cASTNode& node)
2108 {
2109   double scalar = 0.0;
2110   tMatrix<double> op(m->GetNumRows(), m->GetNumCols());
2111 
2112   const sAggregateValue& val = s->GetRow(0)->Get(0);
2113   switch (val.type.type) {
2114     case TYPE(BOOL):    scalar = (val.value.as_bool) ? 1.0 : 0.0; break;
2115     case TYPE(CHAR):    scalar = (double)val.value.as_char; break;
2116     case TYPE(INT):     scalar = (double)val.value.as_int; break;
2117     case TYPE(FLOAT):   scalar = val.value.as_float; break;
2118     case TYPE(STRING):  scalar = val.value.as_string->AsDouble(); break;
2119 
2120     default:
2121       INTERPRET_ERROR(MATRIX_OP_TYPE_MISMATCH, mapToken(TOKEN(OP_MUL)), mapType(val.type));
2122   }
2123 
2124   for (int i = 0; i < m->GetNumRows(); i++) {
2125     cLocalArray* row = m->GetRow(i);
2126     for (int j = 0; j < m->GetNumCols(); j++) {
2127       const sAggregateValue& val = row->Get(j);
2128       switch (val.type.type) {
2129         case TYPE(BOOL):    op[i][j] = (val.value.as_bool) ? 1.0 : 0.0; break;
2130         case TYPE(CHAR):    op[i][j] = (double)val.value.as_char; break;
2131         case TYPE(INT):     op[i][j] = (double)val.value.as_int; break;
2132         case TYPE(FLOAT):   op[i][j] = val.value.as_float; break;
2133         case TYPE(STRING):  op[i][j] = val.value.as_string->AsDouble(); break;
2134 
2135         default:
2136           INTERPRET_ERROR(MATRIX_OP_TYPE_MISMATCH, mapToken(TOKEN(OP_MUL)), mapType(row->Get(j).type));
2137       }
2138     }
2139   }
2140 
2141   int sz_x = m->GetNumRows();
2142   int sz_y = m->GetNumCols();
2143   cLocalMatrix* mat = new cLocalMatrix();
2144   mat->Resize(sz_x, sz_y);
2145 
2146   sASTypeInfo op_type(TYPE(FLOAT));
2147   for (int i = 0; i < sz_x; i++) {
2148     cLocalArray* row = mat->GetRow(i);
2149     for (int j = 0; j < sz_y; j++) {
2150       uAnyType val;
2151       val.as_float = scalar * op[i][j];
2152       row->Set(j, op_type, val);
2153     }
2154   }
2155 
2156   m_rvalue.as_matrix = mat;
2157   m_rtype = TYPE(MATRIX);
2158 }
2159 
matrixMultiply_FullInt(cLocalMatrix * m1,cLocalMatrix * m2,cASTNode & node)2160 void cDirectInterpretASTVisitor::matrixMultiply_FullInt(cLocalMatrix* m1, cLocalMatrix* m2, cASTNode& node)
2161 {
2162   tMatrix<int> op1(m1->GetNumRows(), m1->GetNumCols());
2163   tMatrix<int> op2(m2->GetNumRows(), m2->GetNumCols());
2164 
2165   for (int i = 0; i < m1->GetNumRows(); i++) {
2166     cLocalArray* row = m1->GetRow(i);
2167     for (int j = 0; j < m1->GetNumCols(); j++) {
2168       const sAggregateValue& val = row->Get(j);
2169       switch (val.type.type) {
2170         case TYPE(BOOL):    op1[i][j] = (val.value.as_bool) ? 1 : 0; break;
2171         case TYPE(CHAR):    op1[i][j] = (int)val.value.as_char; break;
2172         case TYPE(INT):     op1[i][j] = val.value.as_int; break;
2173         case TYPE(STRING):  op1[i][j] = val.value.as_string->AsInt(); break;
2174 
2175         default:
2176           INTERPRET_ERROR(MATRIX_OP_TYPE_MISMATCH, mapToken(TOKEN(OP_MUL)), mapType(row->Get(j).type));
2177       }
2178     }
2179   }
2180   for (int i = 0; i < m2->GetNumRows(); i++) {
2181     cLocalArray* row = m2->GetRow(i);
2182     for (int j = 0; j < m2->GetNumCols(); j++) {
2183       const sAggregateValue& val = row->Get(j);
2184       switch (val.type.type) {
2185         case TYPE(BOOL):    op2[i][j] = (val.value.as_bool) ? 1 : 0; break;
2186         case TYPE(CHAR):    op2[i][j] = (int)val.value.as_char; break;
2187         case TYPE(INT):     op2[i][j] = val.value.as_int; break;
2188         case TYPE(STRING):  op2[i][j] = val.value.as_string->AsInt(); break;
2189 
2190         default:
2191           INTERPRET_ERROR(MATRIX_OP_TYPE_MISMATCH, mapToken(TOKEN(OP_MUL)), mapType(row->Get(j).type));
2192       }
2193     }
2194   }
2195 
2196   int sz_x = m1->GetNumRows();
2197   int sz_y = m2->GetNumCols();
2198   cLocalMatrix* mat = new cLocalMatrix();
2199   mat->Resize(sz_x, sz_y);
2200 
2201   sASTypeInfo op_type(TYPE(INT));
2202   for (int i = 0; i < sz_x; i++) {
2203     cLocalArray* row = mat->GetRow(i);
2204     for (int j = 0; j < sz_y; j++) {
2205       uAnyType sum;
2206       sum.as_int = 0;
2207       for (int k = 0; k < m1->GetNumCols(); k++) sum.as_int += op1[i][k] * op2[k][j];
2208       row->Set(j, op_type, sum);
2209     }
2210   }
2211 
2212   m_rvalue.as_matrix = mat;
2213   m_rtype = TYPE(MATRIX);
2214 }
2215 
2216 
matrixMultiply_FullFloat(cLocalMatrix * m1,cLocalMatrix * m2,cASTNode & node)2217 void cDirectInterpretASTVisitor::matrixMultiply_FullFloat(cLocalMatrix* m1, cLocalMatrix* m2, cASTNode& node)
2218 {
2219   tMatrix<double> op1(m1->GetNumRows(), m1->GetNumCols());
2220   tMatrix<double> op2(m2->GetNumRows(), m2->GetNumCols());
2221 
2222   for (int i = 0; i < m1->GetNumRows(); i++) {
2223     cLocalArray* row = m1->GetRow(i);
2224     for (int j = 0; j < m1->GetNumCols(); j++) {
2225       const sAggregateValue& val = row->Get(j);
2226       switch (val.type.type) {
2227         case TYPE(BOOL):    op1[i][j] = (val.value.as_bool) ? 1.0 : 0.0; break;
2228         case TYPE(CHAR):    op1[i][j] = (double)val.value.as_char; break;
2229         case TYPE(INT):     op1[i][j] = (double)val.value.as_int; break;
2230         case TYPE(FLOAT):   op1[i][j] = val.value.as_float; break;
2231         case TYPE(STRING):  op1[i][j] = val.value.as_string->AsDouble(); break;
2232 
2233         default:
2234           INTERPRET_ERROR(MATRIX_OP_TYPE_MISMATCH, mapToken(TOKEN(OP_MUL)), mapType(row->Get(j).type));
2235       }
2236     }
2237   }
2238   for (int i = 0; i < m2->GetNumRows(); i++) {
2239     cLocalArray* row = m2->GetRow(i);
2240     for (int j = 0; j < m2->GetNumCols(); j++) {
2241       const sAggregateValue& val = row->Get(j);
2242       switch (val.type.type) {
2243         case TYPE(BOOL):    op2[i][j] = (val.value.as_bool) ? 1.0 : 0.0; break;
2244         case TYPE(CHAR):    op2[i][j] = (double)val.value.as_char; break;
2245         case TYPE(INT):     op2[i][j] = (double)val.value.as_int; break;
2246         case TYPE(FLOAT):   op2[i][j] = val.value.as_float; break;
2247         case TYPE(STRING):  op2[i][j] = val.value.as_string->AsDouble(); break;
2248 
2249         default:
2250           INTERPRET_ERROR(MATRIX_OP_TYPE_MISMATCH, mapToken(TOKEN(OP_MUL)), mapType(row->Get(j).type));
2251       }
2252     }
2253   }
2254 
2255   int sz_x = m1->GetNumRows();
2256   int sz_y = m2->GetNumCols();
2257   cLocalMatrix* mat = new cLocalMatrix();
2258   mat->Resize(sz_x, sz_y);
2259 
2260   sASTypeInfo op_type(TYPE(FLOAT));
2261   for (int i = 0; i < sz_x; i++) {
2262     cLocalArray* row = mat->GetRow(i);
2263     for (int j = 0; j < sz_y; j++) {
2264       uAnyType sum;
2265       sum.as_float = 0.0;
2266       for (int k = 0; k < m1->GetNumCols(); k++) sum.as_float += op1[i][k] * op2[k][j];
2267       row->Set(j, op_type, sum);
2268     }
2269   }
2270 
2271   m_rvalue.as_matrix = mat;
2272   m_rtype = TYPE(MATRIX);
2273 }
2274 
2275 
2276 
2277 
Cleanup()2278 void cDirectInterpretASTVisitor::sAggregateValue::Cleanup()
2279 {
2280   switch (type.type) {
2281     case TYPE(ARRAY):       value.as_array->RemoveReference(); break;
2282     case TYPE(DICT):        value.as_dict->RemoveReference(); break;
2283     case TYPE(MATRIX):      value.as_matrix->RemoveReference(); break;
2284     case TYPE(OBJECT_REF):  delete value.as_ref; break;
2285     case TYPE(STRING):      delete value.as_string; break;
2286     default: break;
2287   }
2288 }
2289 
operator ==(const sAggregateValue & lval)2290 bool cDirectInterpretASTVisitor::sAggregateValue::operator==(const sAggregateValue& lval)
2291 {
2292   if (type == lval.type) {
2293     switch (type.type) {
2294       case TYPE(BOOL):    return value.as_bool == lval.value.as_bool;
2295       case TYPE(CHAR):    return value.as_char == lval.value.as_char;
2296       case TYPE(INT):     return value.as_int == lval.value.as_int;
2297       case TYPE(FLOAT):   return value.as_float == lval.value.as_float;
2298       case TYPE(STRING):  return *value.as_string == *lval.value.as_string;
2299       case TYPE(ARRAY):   return value.as_array == lval.value.as_array;
2300       case TYPE(DICT):    return value.as_dict == lval.value.as_dict;
2301       case TYPE(MATRIX):  return value.as_matrix == lval.value.as_matrix;
2302       case TYPE(OBJECT_REF): return value.as_nobj == lval.value.as_nobj;
2303 
2304       default:
2305         break;
2306     }
2307   }
2308 
2309   return false;
2310 }
2311 
Set(int i,const sASTypeInfo & type,uAnyType value)2312 void cDirectInterpretASTVisitor::cLocalArray::Set(int i, const sASTypeInfo& type, uAnyType value)
2313 {
2314   m_storage[i].Cleanup();
2315 
2316   m_storage[i].type = type;
2317 
2318   switch (type.type) {
2319     case TYPE(BOOL):
2320     case TYPE(CHAR):
2321     case TYPE(INT):
2322     case TYPE(FLOAT):
2323       m_storage[i].value = value;
2324       break;
2325 
2326     case TYPE(STRING):
2327       m_storage[i].value.as_string = new cString(*value.as_string);
2328       break;
2329 
2330     case TYPE(ARRAY):
2331       m_storage[i].value.as_array = value.as_array->GetReference();
2332       break;
2333 
2334     case TYPE(DICT):
2335       m_storage[i].value.as_dict = value.as_dict->GetReference();
2336       break;
2337 
2338     case TYPE(MATRIX):
2339       m_storage[i].value.as_matrix = value.as_matrix->GetReference();
2340       break;
2341 
2342     default: break;
2343   }
2344 
2345 }
2346 
copy(int offset,tArray<sAggregateValue> & in_storage)2347 void cDirectInterpretASTVisitor::cLocalArray::copy(int offset, tArray<sAggregateValue>& in_storage)
2348 {
2349   for (int i = 0; i < in_storage.GetSize(); i++) {
2350     m_storage[i + offset].type = in_storage[i].type;
2351     switch (in_storage[i].type.type) {
2352       case TYPE(BOOL):    m_storage[i + offset].value.as_bool = in_storage[i].value.as_bool; break;
2353       case TYPE(CHAR):    m_storage[i + offset].value.as_char = in_storage[i].value.as_char; break;
2354       case TYPE(INT):     m_storage[i + offset].value.as_int = in_storage[i].value.as_int; break;
2355       case TYPE(FLOAT):   m_storage[i + offset].value.as_float = in_storage[i].value.as_float; break;
2356       case TYPE(STRING):  m_storage[i + offset].value.as_string = new cString(*in_storage[i].value.as_string); break;
2357       case TYPE(ARRAY):   m_storage[i + offset].value.as_array = in_storage[i].value.as_array->GetReference(); break;
2358       case TYPE(DICT):    m_storage[i + offset].value.as_dict = in_storage[i].value.as_dict->GetReference(); break;
2359       case TYPE(MATRIX):  m_storage[i + offset].value.as_matrix = in_storage[i].value.as_matrix->GetReference(); break;
2360 
2361       default: break;
2362     }
2363   }
2364 }
2365 
2366 
Resize(int sz)2367 void cDirectInterpretASTVisitor::cLocalArray::Resize(int sz)
2368 {
2369   int o_sz = m_storage.GetSize();
2370 
2371   // Cleanup values if we are shrinking
2372   for (int i = sz; i < o_sz; i++) m_storage[i].Cleanup();
2373 
2374   m_storage.Resize(sz);
2375 
2376   // Initialize values if we are growing
2377   for (int i = o_sz; i < sz; i++) {
2378     m_storage[i].value.as_int = 0;
2379     m_storage[i].type = TYPE(INT);
2380   }
2381 }
2382 
SetWithArray(cLocalArray * arr)2383 void cDirectInterpretASTVisitor::cLocalArray::SetWithArray(cLocalArray* arr)
2384 {
2385   Resize(arr->GetSize());
2386 
2387   for (int i = 0; i < arr->GetSize(); i++) Set(i, arr->Get(i));
2388 }
2389 
SetWithKeys(cLocalDict * dict)2390 void cDirectInterpretASTVisitor::cLocalArray::SetWithKeys(cLocalDict* dict)
2391 {
2392   Resize(0);
2393 
2394   dict->GetKeys(m_storage);
2395 
2396   for (int i = 0; i < m_storage.GetSize(); i++) {
2397     switch (m_storage[i].type.type) {
2398       case TYPE(STRING):  m_storage[i].value.as_string = new cString(*m_storage[i].value.as_string); break;
2399       case TYPE(ARRAY):   m_storage[i].value.as_array->GetReference(); break;
2400       case TYPE(DICT):    m_storage[i].value.as_dict->GetReference(); break;
2401       case TYPE(MATRIX):  m_storage[i].value.as_matrix->GetReference(); break;
2402 
2403       default: break;
2404     }
2405   }
2406 }
2407 
2408 
SetWithValues(cLocalDict * dict)2409 void cDirectInterpretASTVisitor::cLocalArray::SetWithValues(cLocalDict* dict)
2410 {
2411   Resize(0);
2412 
2413   dict->GetValues(m_storage);
2414 
2415   for (int i = 0; i < m_storage.GetSize(); i++) {
2416     switch (m_storage[i].type.type) {
2417       case TYPE(STRING):  m_storage[i].value.as_string = new cString(*m_storage[i].value.as_string); break;
2418       case TYPE(ARRAY):   m_storage[i].value.as_array->GetReference(); break;
2419       case TYPE(DICT):    m_storage[i].value.as_dict->GetReference(); break;
2420       case TYPE(MATRIX):  m_storage[i].value.as_matrix->GetReference(); break;
2421 
2422       default: break;
2423     }
2424   }
2425 }
2426 
2427 
~cLocalArray()2428 cDirectInterpretASTVisitor::cLocalArray::~cLocalArray()
2429 {
2430   int sz = m_storage.GetSize();
2431 
2432   // Cleanup values stored in the array
2433   for (int i = 0; i < sz; i++) m_storage[i].Cleanup();
2434 }
2435 
2436 
Resize(int sz_x,int sz_y)2437 void cDirectInterpretASTVisitor::cLocalMatrix::Resize(int sz_x, int sz_y)
2438 {
2439   int o_sz = m_storage.GetSize();
2440   m_storage.Resize(sz_x);
2441 
2442   // Resize the columns
2443   for (int i = (m_sz_y == sz_y) ? o_sz : 0; i < sz_x; i++) {
2444     m_storage[i].SetNonResizable();
2445     m_storage[i].Resize(sz_y);
2446   }
2447 
2448   m_sz_y = sz_y;
2449 }
2450 
2451 
2452 
2453 
Set(const sAggregateValue & idx,const sAggregateValue & val)2454 void cDirectInterpretASTVisitor::cLocalDict::Set(const sAggregateValue& idx, const sAggregateValue& val)
2455 {
2456   sAggregateValue o_val;
2457   if (m_storage.Find(idx, o_val)) {
2458     o_val.Cleanup();
2459     m_storage.SetValue(idx, val);
2460   } else {
2461     m_storage.SetValue(idx, val);
2462   }
2463 
2464 }
2465 
Clear()2466 void cDirectInterpretASTVisitor::cLocalDict::Clear()
2467 {
2468   tList<sAggregateValue> keys;
2469   tList<sAggregateValue> vals;
2470 
2471   m_storage.AsListsUnsorted(keys, vals);
2472 
2473   sAggregateValue* av = NULL;
2474 
2475   tListIterator<sAggregateValue> kit(keys);
2476   while ((av = kit.Next())) av->Cleanup();
2477 
2478   tListIterator<sAggregateValue> vit(vals);
2479   while ((av = vit.Next())) av->Cleanup();
2480 
2481   m_storage.ClearAll();
2482 }
2483 
~cLocalDict()2484 cDirectInterpretASTVisitor::cLocalDict::~cLocalDict()
2485 {
2486   tList<sAggregateValue> keys;
2487   tList<sAggregateValue> vals;
2488 
2489   m_storage.AsListsUnsorted(keys, vals);
2490 
2491   sAggregateValue* av = NULL;
2492 
2493   tListIterator<sAggregateValue> kit(keys);
2494   while ((av = kit.Next())) av->Cleanup();
2495 
2496   tListIterator<sAggregateValue> vit(vals);
2497   while ((av = vit.Next())) av->Cleanup();
2498 }
2499 
2500 
Get(const sAggregateValue & idx,sAggregateValue & val)2501 bool cDirectInterpretASTVisitor::cArrayVarRef::Get(const sAggregateValue& idx, sAggregateValue& val)
2502 {
2503   int idxi = -1;
2504   switch (idx.type.type) {
2505     case TYPE(BOOL):        idxi = (idx.value.as_bool) ? 1 : 0; break;
2506     case TYPE(CHAR):        idxi = (int)idx.value.as_char; break;
2507     case TYPE(INT):         idxi = idx.value.as_int; break;
2508     case TYPE(FLOAT):       idxi = (int)idx.value.as_float; break;
2509     case TYPE(STRING):      idxi = idx.value.as_string->AsInt(); break;
2510     default: break;
2511   }
2512 
2513   if (idxi < 0 || idxi >= m_var.as_array->GetSize()) return false;
2514 
2515   val = m_var.as_array->Get(idxi);
2516   return true;
2517 }
2518 
Set(sAggregateValue & idx,sAggregateValue & val)2519 bool cDirectInterpretASTVisitor::cArrayVarRef::Set(sAggregateValue& idx, sAggregateValue& val)
2520 {
2521   int idxi = -1;
2522   switch (idx.type.type) {
2523     case TYPE(BOOL):        idxi = (idx.value.as_bool) ? 1 : 0; break;
2524     case TYPE(CHAR):        idxi = (int)idx.value.as_char; break;
2525     case TYPE(INT):         idxi = idx.value.as_int; break;
2526     case TYPE(FLOAT):       idxi = (int)idx.value.as_float; break;
2527     case TYPE(STRING):      idxi = idx.value.as_string->AsInt(); delete idx.value.as_string; break;
2528     case TYPE(ARRAY):       idx.value.as_array->RemoveReference(); break;
2529     case TYPE(DICT):        idx.value.as_dict->RemoveReference(); break;
2530     case TYPE(MATRIX):      idx.value.as_matrix->RemoveReference(); break;
2531     case TYPE(OBJECT_REF):  delete idx.value.as_ref; break;
2532     default: break;
2533   }
2534 
2535   if (idxi < 0 || idxi >= m_var.as_array->GetSize()) return false;
2536 
2537   m_var.as_array->Set(idxi, val.type, val.value);
2538 
2539   return true;
2540 }
2541 
2542 
Get(const sAggregateValue & idx,sAggregateValue & val)2543 bool cDirectInterpretASTVisitor::cDictVarRef::Get(const sAggregateValue& idx, sAggregateValue& val)
2544 {
2545   return m_var.as_dict->Get(idx, val);
2546 }
2547 
Set(sAggregateValue & idx,sAggregateValue & val)2548 bool cDirectInterpretASTVisitor::cDictVarRef::Set(sAggregateValue& idx, sAggregateValue& val)
2549 {
2550   m_var.as_dict->Set(idx, val);
2551   return true;
2552 }
2553 
2554 
Get(const sAggregateValue & idx,sAggregateValue & val)2555 bool cDirectInterpretASTVisitor::cMatrixVarRef::Get(const sAggregateValue& idx, sAggregateValue& val)
2556 {
2557   int idxi = -1;
2558   switch (idx.type.type) {
2559     case TYPE(BOOL):        idxi = (idx.value.as_bool) ? 1 : 0; break;
2560     case TYPE(CHAR):        idxi = (int)idx.value.as_char; break;
2561     case TYPE(INT):         idxi = idx.value.as_int; break;
2562     case TYPE(FLOAT):       idxi = (int)idx.value.as_float; break;
2563     case TYPE(STRING):      idxi = idx.value.as_string->AsInt(); break;
2564     default: break;
2565   }
2566 
2567   if (idxi < 0 || idxi >= m_var.as_matrix->GetNumRows()) return false;
2568 
2569   val.value.as_array = m_var.as_matrix->GetRow(idxi);
2570   val.type = TYPE(ARRAY);
2571   return true;
2572 }
2573 
Set(sAggregateValue & idx,sAggregateValue & val)2574 bool cDirectInterpretASTVisitor::cMatrixVarRef::Set(sAggregateValue& idx, sAggregateValue& val)
2575 {
2576   int idxi = -1;
2577   switch (idx.type.type) {
2578     case TYPE(BOOL):        idxi = (idx.value.as_bool) ? 1 : 0; break;
2579     case TYPE(CHAR):        idxi = (int)idx.value.as_char; break;
2580     case TYPE(INT):         idxi = idx.value.as_int; break;
2581     case TYPE(FLOAT):       idxi = (int)idx.value.as_float; break;
2582     case TYPE(STRING):      idxi = idx.value.as_string->AsInt(); delete idx.value.as_string; break;
2583     case TYPE(ARRAY):       idx.value.as_array->RemoveReference(); break;
2584     case TYPE(DICT):        idx.value.as_dict->RemoveReference(); break;
2585     case TYPE(MATRIX):      idx.value.as_matrix->RemoveReference(); break;
2586     case TYPE(OBJECT_REF):  delete idx.value.as_ref; break;
2587     default: break;
2588   }
2589 
2590   if (idxi < 0 || idxi >= m_var.as_matrix->GetNumRows()) return false;
2591 
2592   if (m_var.as_matrix->GetNumCols() == 0) return false;
2593   if (val.type.type != TYPE(ARRAY)) return false;
2594   if (val.value.as_array->GetSize() != m_var.as_matrix->GetNumCols()) return false;
2595   m_var.as_matrix->Set(idxi, val.value.as_array);
2596 
2597   return true;
2598 }
2599 
2600 
Get(const sAggregateValue & idx,sAggregateValue & val)2601 bool cDirectInterpretASTVisitor::cNativeObjectVarRef::Get(const sAggregateValue& idx, sAggregateValue& val)
2602 {
2603   // @AS_TODO - get indexed native var
2604   return false;
2605 }
2606 
Set(sAggregateValue & idx,sAggregateValue & val)2607 bool cDirectInterpretASTVisitor::cNativeObjectVarRef::Set(sAggregateValue& idx, sAggregateValue& val)
2608 {
2609   // @AS_TODO - set indexed native var
2610   return false;
2611 }
2612 
2613 
2614 
2615 
Get(const sAggregateValue & idx,sAggregateValue & val)2616 bool cDirectInterpretASTVisitor::cObjectIndexRef::Get(const sAggregateValue& idx, sAggregateValue& val)
2617 {
2618   sAggregateValue o_val;
2619 
2620   if (!m_obj->Get(m_idx, o_val)) return false;
2621 
2622   switch (o_val.type.type) {
2623     case TYPE(ARRAY):
2624       {
2625         cLocalArray* arr = o_val.value.as_array;
2626 
2627         int idxi = -1;
2628         switch (idx.type.type) {
2629           case TYPE(BOOL):        idxi = (idx.value.as_bool) ? 1 : 0; break;
2630           case TYPE(CHAR):        idxi = (int)idx.value.as_char; break;
2631           case TYPE(INT):         idxi = idx.value.as_int; break;
2632           case TYPE(FLOAT):       idxi = (int)idx.value.as_float; break;
2633           case TYPE(STRING):      idxi = idx.value.as_string->AsInt(); break;
2634           default: break;
2635         }
2636         if (idxi < 0 || idxi >= arr->GetSize()) return false;
2637         val = arr->Get(idxi);
2638         return true;
2639       }
2640 
2641     case TYPE(DICT):
2642       return o_val.value.as_dict->Get(idx, val);
2643 
2644     case TYPE(MATRIX):
2645       {
2646         cLocalMatrix* mat = o_val.value.as_matrix;
2647 
2648         int idxi = -1;
2649         switch (idx.type.type) {
2650           case TYPE(BOOL):        idxi = (idx.value.as_bool) ? 1 : 0; break;
2651           case TYPE(CHAR):        idxi = (int)idx.value.as_char; break;
2652           case TYPE(INT):         idxi = idx.value.as_int; break;
2653           case TYPE(FLOAT):       idxi = (int)idx.value.as_float; break;
2654           case TYPE(STRING):      idxi = idx.value.as_string->AsInt(); break;
2655           default: break;
2656         }
2657         if (idxi < 0 || idxi >= mat->GetNumRows()) return false;
2658         val.value.as_array = mat->GetRow(idxi);
2659         val.type = TYPE(ARRAY);
2660         return true;
2661       }
2662 
2663     default:
2664       break;
2665   }
2666 
2667 
2668   return false;
2669 }
2670 
2671 
Set(sAggregateValue & idx,sAggregateValue & val)2672 bool cDirectInterpretASTVisitor::cObjectIndexRef::Set(sAggregateValue& idx, sAggregateValue& val)
2673 {
2674   sAggregateValue o_val;
2675 
2676   if (!m_obj->Get(m_idx, o_val)) {
2677     idx.Cleanup();
2678     return false;
2679   }
2680 
2681   switch (o_val.type.type) {
2682     case TYPE(ARRAY):
2683       {
2684         cLocalArray* arr = o_val.value.as_array;
2685 
2686         int idxi = -1;
2687         switch (idx.type.type) {
2688           case TYPE(BOOL):        idxi = (idx.value.as_bool) ? 1 : 0; break;
2689           case TYPE(CHAR):        idxi = (int)idx.value.as_char; break;
2690           case TYPE(INT):         idxi = idx.value.as_int; break;
2691           case TYPE(FLOAT):       idxi = (int)idx.value.as_float; break;
2692           case TYPE(STRING):      idxi = idx.value.as_string->AsInt(); delete idx.value.as_string; break;
2693           case TYPE(ARRAY):       idx.value.as_array->RemoveReference(); break;
2694           case TYPE(DICT):        idx.value.as_dict->RemoveReference(); break;
2695           case TYPE(MATRIX):      idx.value.as_matrix->RemoveReference(); break;
2696           case TYPE(OBJECT_REF):  delete idx.value.as_ref; break;
2697           default: break;
2698         }
2699         if (idxi < 0 || idxi >= arr->GetSize()) return false;
2700 
2701         arr->Set(idxi, val.type, val.value);
2702       }
2703       return true;
2704 
2705     case TYPE(DICT):
2706       o_val.value.as_dict->Set(idx, val);
2707       return true;
2708 
2709     case TYPE(MATRIX):
2710       {
2711         cLocalMatrix* mat = o_val.value.as_matrix;
2712 
2713         int idxi = -1;
2714         switch (idx.type.type) {
2715           case TYPE(BOOL):        idxi = (idx.value.as_bool) ? 1 : 0; break;
2716           case TYPE(CHAR):        idxi = (int)idx.value.as_char; break;
2717           case TYPE(INT):         idxi = idx.value.as_int; break;
2718           case TYPE(FLOAT):       idxi = (int)idx.value.as_float; break;
2719           case TYPE(STRING):      idxi = idx.value.as_string->AsInt(); delete idx.value.as_string; break;
2720           case TYPE(ARRAY):       idx.value.as_array->RemoveReference(); break;
2721           case TYPE(DICT):        idx.value.as_dict->RemoveReference(); break;
2722           case TYPE(MATRIX):      idx.value.as_matrix->RemoveReference(); break;
2723           case TYPE(OBJECT_REF):  delete idx.value.as_ref; break;
2724           default: break;
2725         }
2726         if (idxi < 0 || idxi >= mat->GetNumRows()) return false;
2727 
2728         if (mat->GetNumCols() == 0) return false;
2729         if (val.type.type != TYPE(ARRAY)) return false;
2730         if (val.value.as_array->GetSize() != mat->GetNumCols()) return false;
2731         mat->Set(idxi, val.value.as_array);
2732       }
2733       return true;
2734 
2735     default:
2736       break;
2737   }
2738 
2739   idx.Cleanup();
2740   return false;
2741 }
2742 
2743 
Get(const sAggregateValue & idx,sAggregateValue & val)2744 bool cDirectInterpretASTVisitor::cStringVarRef::Get(const sAggregateValue& idx, sAggregateValue& val)
2745 {
2746   int idxi = -1;
2747   switch (idx.type.type) {
2748     case TYPE(BOOL):        idxi = (idx.value.as_bool) ? 1 : 0; break;
2749     case TYPE(CHAR):        idxi = (int)idx.value.as_char; break;
2750     case TYPE(INT):         idxi = idx.value.as_int; break;
2751     case TYPE(FLOAT):       idxi = (int)idx.value.as_float; break;
2752     case TYPE(STRING):      idxi = idx.value.as_string->AsInt(); break;
2753     default: break;
2754   }
2755 
2756   if (idxi < 0 || idxi >= m_var.as_string->GetSize()) return false;
2757 
2758   val.value.as_char = (*m_var.as_string)[idxi];
2759   val.type = TYPE(CHAR);
2760   return true;
2761 }
2762 
Set(sAggregateValue & idx,sAggregateValue & val)2763 bool cDirectInterpretASTVisitor::cStringVarRef::Set(sAggregateValue& idx, sAggregateValue& val)
2764 {
2765   int idxi = -1;
2766   switch (idx.type.type) {
2767     case TYPE(BOOL):        idxi = (idx.value.as_bool) ? 1 : 0; break;
2768     case TYPE(CHAR):        idxi = (int)idx.value.as_char; break;
2769     case TYPE(INT):         idxi = idx.value.as_int; break;
2770     case TYPE(FLOAT):       idxi = (int)idx.value.as_float; break;
2771     case TYPE(STRING):      idxi = idx.value.as_string->AsInt(); delete idx.value.as_string; break;
2772     case TYPE(ARRAY):       idx.value.as_array->RemoveReference(); break;
2773     case TYPE(DICT):        idx.value.as_dict->RemoveReference(); break;
2774     case TYPE(MATRIX):      idx.value.as_matrix->RemoveReference(); break;
2775     case TYPE(OBJECT_REF):  delete idx.value.as_ref; break;
2776     default: break;
2777   }
2778 
2779   if (idxi < 0 || idxi >= m_var.as_string->GetSize()) return false;
2780 
2781   switch (val.type.type) {
2782     case TYPE(BOOL):  (*m_var.as_string)[idxi] = (val.value.as_bool) ? 1 : 0; break;
2783     case TYPE(CHAR):  (*m_var.as_string)[idxi] = val.value.as_char; break;
2784     case TYPE(INT):   (*m_var.as_string)[idxi] = (char)val.value.as_int; break;
2785 
2786     default:
2787       return false;
2788   }
2789 
2790   return true;
2791 }
2792 
2793 
2794 
reportError(ASDirectInterpretError_t err,const cASFilePosition & fp,const int line,...)2795 void cDirectInterpretASTVisitor::reportError(ASDirectInterpretError_t err, const cASFilePosition& fp, const int line, ...)
2796 {
2797 #if DEBUG_AS_DIRECT_INTERPRET
2798 # define ERR_ENDL "  (cDirectInterpretASTVisitor.cc:" << line << ")" << std::endl
2799 #else
2800 # define ERR_ENDL std::endl
2801 #endif
2802 
2803 #define VA_ARG_STR va_arg(vargs, const char*)
2804 
2805   std::cerr << fp.GetFilename() << ":" << fp.GetLineNumber() << ": error: ";
2806 
2807   va_list vargs;
2808   va_start(vargs, line);
2809   switch (err) {
2810     case AS_DIRECT_INTERPRET_ERR_CANNOT_RESIZE_MATRIX_ROW:
2811       std::cerr << "cannot directly resize matrix row" << ERR_ENDL;
2812       break;
2813     case AS_DIRECT_INTERPRET_ERR_DIVISION_BY_ZERO:
2814       std::cerr << "division by zero" << ERR_ENDL;
2815       break;
2816     case AS_DIRECT_INTERPRET_ERR_INDEX_ERROR:
2817       std::cerr << "index operation failed" << ERR_ENDL;
2818       break;
2819     case AS_DIRECT_INTERPRET_ERR_INDEX_OUT_OF_BOUNDS:
2820       std::cerr << "array index out of bounds" << ERR_ENDL;
2821       break;
2822     case AS_DIRECT_INTERPRET_ERR_INVALID_ARRAY_SIZE:
2823       std::cerr << "invalid array dimension" << ERR_ENDL;
2824       break;
2825     case AS_DIRECT_INTERPRET_ERR_KEY_NOT_FOUND:
2826       std::cerr << "key not found" << ERR_ENDL;
2827       break;
2828     case AS_DIRECT_INTERPRET_ERR_MATRIX_OP_TYPE_MISMATCH:
2829       {
2830         const char* op = VA_ARG_STR;
2831         const char* type = VA_ARG_STR;
2832         std::cerr << "matrix '" << op << "' undefined for contained value of type '" << type << "'" << ERR_ENDL;
2833       }
2834       break;
2835     case AS_DIRECT_INTERPRET_ERR_MATRIX_SIZE_MISMATCH:
2836       std::cerr << "matrix size mismatch for '" << VA_ARG_STR << "' operation" << ERR_ENDL;
2837       break;
2838     case AS_DIRECT_INTERPRET_ERR_NOBJ_METHOD_LOOKUP_FAILED:
2839       {
2840         const char* meth = VA_ARG_STR;
2841         const char* itype = VA_ARG_STR;
2842         std::cerr << "method '" << meth << "' not supported by '" << itype << "'" << ERR_ENDL;
2843       }
2844       break;
2845     case AS_DIRECT_INTERPRET_ERR_NOBJ_TYPE_MISMATCH:
2846       {
2847         const char* otype = VA_ARG_STR;
2848         const char* itype = VA_ARG_STR;
2849         std::cerr << "expected object of type '" << otype << "', received '" << itype << "'" << ERR_ENDL;
2850       }
2851       break;
2852     case AS_DIRECT_INTERPRET_ERR_OBJECT_ASSIGN_FAIL:
2853       std::cerr << "aggregate assignment failed" << ERR_ENDL;
2854       break;
2855     case AS_DIRECT_INTERPRET_ERR_TYPE_CAST:
2856       {
2857         const char* type1 = VA_ARG_STR;
2858         const char* type2 = VA_ARG_STR;
2859         std::cerr << "cannot convert '" << type1 << "' to '" << type2 << "'" << ERR_ENDL;
2860       }
2861       break;
2862     case AS_DIRECT_INTERPRET_ERR_UNDEFINED_TYPE_OP:
2863       {
2864         const char* op = VA_ARG_STR;
2865         const char* type = VA_ARG_STR;
2866         std::cerr << "'" << op << "' operation undefined for type '" << type << "'" << ERR_ENDL;
2867       }
2868       break;
2869     case AS_DIRECT_INTERPRET_ERR_UNPACK_VALUE_TOO_LARGE:
2870       std::cerr << "unpack value too large" << ERR_ENDL;
2871       break;
2872     case AS_DIRECT_INTERPRET_ERR_UNPACK_VALUE_TOO_SMALL:
2873       std::cerr << "unpack value too small" << ERR_ENDL;
2874       break;
2875 
2876     case AS_DIRECT_INTERPRET_ERR_INTERNAL:
2877       std::cerr << "internal interpreter error at cDirectInterpretASTVisitor.cc:" << line << std::endl;
2878       break;
2879     case AS_DIRECT_INTERPRET_ERR_UNKNOWN:
2880     default:
2881       std::cerr << "unknown error" << std::endl;
2882   }
2883   va_end(vargs);
2884 
2885   exit(AS_EXIT_FAIL_INTERPRET);
2886 
2887 #undef ERR_ENDL
2888 #undef VA_ARG_STR
2889 }
2890 
2891 #undef INTERPRET_ERROR()
2892 #undef TOKEN()
2893 #undef TYPE()
2894