1 // Copyright (c) 2010 Giovanni Lagorio (lagorio@disi.unige.it)
2 //
3 // This file is part of the source of CoCoALib, the CoCoA Library.
4 //
5 // CoCoALib is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // CoCoALib is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with CoCoALib. If not, see <http://www.gnu.org/licenses/>.
17
18 #include "CoCoA/BigIntOps.H"
19 #include "CoCoA/MatrixOps.H"
20 #include "CoCoA/QuotientRing.H"
21 #include "CoCoA/RingQQ.H"
22 #include "CoCoA/RingZZ.H"
23 #include "CoCoA/SparsePolyRing.H"
24 #include "CoCoA/convert.H"
25 #include "CoCoA/error.H"
26
27 #include <limits>
28 #include <iostream>
29 #include <exception>
30 #include <cassert>
31 #include <errno.h>
32 #include <set>
33 #include <boost/scope_exit.hpp>
34 #include <boost/foreach.hpp>
35 #include <boost/algorithm/string/case_conv.hpp>
36
37 //#include "CoCoA/library.H" // already included by AST->Parser->Interpreter
38 #include "Interpreter.H"
39 #include "globals.H"
40 #include "BuiltInFunctions.H"
41 #include "CoCoALibSupplement.H"
42 #include "OnlineHelp.H"
43
44 namespace CoCoA {
45
46 namespace InterpreterNS {
47
48 using namespace std;
49 using namespace boost;
50 using namespace CoCoA::AST;
51 using namespace CoCoA::LexerNS;
52 using namespace CoCoA::ParserNS;
53
54 intrusive_ptr<BOOL> BOOL::trueValue(new BOOL(true)), BOOL::falseValue(new BOOL(false));
55 intrusive_ptr<INT> INT::zero(new INT(BigInt(0))), INT::one(new INT(BigInt(1))), INT::minusOne(new INT(BigInt(-1)));
56 intrusive_ptr<STRING> STRING::empty(new STRING(""));
57
58 namespace
59 {
ringForList(const intrusive_ptr<const LIST> list)60 ring ringForList(const intrusive_ptr<const LIST> list) {
61 bool foundBigRat = false;
62 const LIST::ContainerType::size_type size = list->size();
63 for(LIST::ContainerType::size_type a=0; a<size; ++a) {
64 const intrusive_ptr<RightValue> e = list->getValue(a);
65 if (const intrusive_ptr<RINGELEM> ringElem = dynamic_pointer_cast<RINGELEM>(e))
66 return owner(ringElem->theRingElem);
67 else if (dynamic_pointer_cast<RAT>(e))
68 foundBigRat = true;
69 }
70 if (foundBigRat)
71 return RingQQ();
72 return RingZZ();
73 }
74
toRingElemList(const intrusive_ptr<const LIST> list,const intrusive_ptr<const Expression> exp,const ring & ring)75 vector<RingElem> toRingElemList(const intrusive_ptr<const LIST> list, const intrusive_ptr<const Expression> exp, const ring &ring) {
76 const LIST::ContainerType::size_type size = list->size();
77 vector<RingElem> result;
78 for(LIST::ContainerType::size_type a=0; a<size; ++a) {
79 const intrusive_ptr<RightValue> e = list->getValue(a);
80 if (const intrusive_ptr<RINGELEM> ringElem = dynamic_pointer_cast<RINGELEM>(e))
81 result.push_back(ringElem->theRingElem);
82 else if (const intrusive_ptr<INT> N = dynamic_pointer_cast<INT>(e))
83 result.push_back(RingElem(ring, N->theBigInt));
84 else if (const intrusive_ptr<RAT> qq = dynamic_pointer_cast<RAT>(e))
85 result.push_back(RingElem(ring, qq->theBigRat));
86 else
87 throw RuntimeException("A list containing RINGELEM, INT or RAT values is required", exp);
88 }
89 return result;
90 }
91
92 }
93
evalArgAsListOfRingElem(const ring & ring,const Argument & arg)94 vector<RingElem> RuntimeEnvironment::evalArgAsListOfRingElem(const ring &ring, const Argument &arg) {
95 return toRingElemList(this->evalArgAs<LIST>(arg), arg.exp, ring);
96 }
97
98
evalArgAsListOfRingElem(const Argument & arg)99 vector<RingElem> RuntimeEnvironment::evalArgAsListOfRingElem(const Argument &arg) {
100 const intrusive_ptr<const LIST> list = this->evalArgAs<LIST>(arg);
101 return toRingElemList(list, arg.exp, ringForList(list));
102 }
103
104
evalRVAsListOfRingElem(const boost::intrusive_ptr<const RightValue> rightOp,const Argument & arg)105 vector<RingElem> RuntimeEnvironment::evalRVAsListOfRingElem(const boost::intrusive_ptr<const RightValue> rightOp, const Argument &arg) {
106 const intrusive_ptr<const LIST> list = boost::dynamic_pointer_cast<const LIST>(rightOp);
107 return toRingElemList(list, arg.exp, ringForList(list));
108 }
109
110
evalArgAsListOfSymbols(const Argument & arg)111 vector<symbol> RuntimeEnvironment::evalArgAsListOfSymbols(const Argument &arg)
112 {
113 intrusive_ptr<const RightValue> v=this->evalArgAs<RightValue>(arg);
114 int which;
115 v = this->evalArgAsT1orT2<STRING, LIST>(arg, which);
116 switch (which)
117 {
118 case 1: return symbols(RefTo<string>(v));
119 case 2:
120 {
121 vector<symbol> syms;
122 intrusive_ptr<LIST> l = this->evalArgAs<LIST>(arg);
123 LIST::ContainerType::size_type size = l->size();
124 for (unsigned long i=0; i<size; ++i)
125 {
126 if (const boost::intrusive_ptr<STRING> s = boost::dynamic_pointer_cast<STRING>(l->getValue(i)))
127 { syms.push_back(symbol(s->theString)); continue; }
128 if (const boost::intrusive_ptr<RECORD> r = boost::dynamic_pointer_cast<RECORD>(l->getValue(i)))
129 {
130 if (!r->getFieldNoCheck("head"))
131 throw RuntimeException("record must have \"head\" field (\"indices\" field is optional)", arg.exp);
132
133 const boost::intrusive_ptr<STRING> s = boost::dynamic_pointer_cast<STRING>(r->getFieldNoCheck("head"));
134 if (s == nullptr) throw RuntimeException("field \"head\" must be a string", arg.exp);
135
136 if (!r->getFieldNoCheck("indices"))
137 { syms.push_back(symbol(s->theString)); continue;}
138
139 vector<long> indices;
140 const boost::intrusive_ptr<LIST> inds = boost::dynamic_pointer_cast<LIST>(r->getFieldNoCheck("indices"));
141 if (inds == nullptr) throw RuntimeException("field \"indices\" must be a list (of integers)", arg.exp);
142 long tmp;
143 LIST::ContainerType::size_type NumIndices = inds->size();
144 for (unsigned long j=0; j<NumIndices; ++j)
145 {
146 if (boost::dynamic_pointer_cast<INT>(inds->getValue(j)) == nullptr)
147 throw RuntimeException("Indices must be integers", arg.exp);
148
149 if (IsConvertible(tmp, (boost::dynamic_pointer_cast<INT>(inds->getValue(j)))->theBigInt))
150 indices.push_back(tmp);
151 else
152 throw RuntimeException("All indices must fit into a machine-integer", arg.exp);
153 }
154 syms.push_back(symbol(s->theString, indices));
155 }
156 else throw RuntimeException("List of symbols must have strings or records", arg.exp);
157 };
158 return syms;
159 }; // LIST
160 default: throw RuntimeException(ERRORMissingCode(v), arg.exp);
161 }
162 }
163
164
evalArgAsLong(const Argument & arg)165 long RuntimeEnvironment::evalArgAsLong(const Argument &arg) {
166 const intrusive_ptr<INT> N = this->evalArgAs<INT>(arg);
167 long n;
168 if (!IsConvertible(n, N->theBigInt))
169 throw RuntimeException("number is too big", arg.exp);
170 return n;
171 }
172
indexedByBigInt(intrusive_ptr<INT> index,const CharPointer & targetExpBegin,const CharPointer & targetExpEnd,const CharPointer & indexExpBegin,const CharPointer & indexExpEnd)173 intrusive_ptr<Value> LeftValue::indexedByBigInt(intrusive_ptr<INT> index, const CharPointer &targetExpBegin, const CharPointer &targetExpEnd, const CharPointer &indexExpBegin, const CharPointer &indexExpEnd) {
174 return new IntegerIndexedAccess(this, index->theBigInt, targetExpBegin, targetExpEnd, indexExpBegin, indexExpEnd);
175 }
176
indexedByString(intrusive_ptr<STRING> index,const CharPointer & targetExpBegin,const CharPointer & targetExpEnd,const CharPointer & indexExpBegin,const CharPointer & indexExpEnd)177 intrusive_ptr<Value> LeftValue::indexedByString(intrusive_ptr<STRING> index, const CharPointer &targetExpBegin, const CharPointer &targetExpEnd, const CharPointer &indexExpBegin, const CharPointer &indexExpEnd) {
178 return new StringIndexedAccess(this, index->theString, targetExpBegin, targetExpEnd, indexExpBegin, indexExpEnd);
179 }
180
indexedByBigInt(intrusive_ptr<INT>,const CharPointer & targetExpBegin,const CharPointer & targetExpEnd,const CharPointer &,const CharPointer &)181 intrusive_ptr<Value> RightValue::indexedByBigInt(intrusive_ptr<INT> /* index */, const CharPointer &targetExpBegin, const CharPointer &targetExpEnd, const CharPointer & /* indexExpBegin */, const CharPointer & /* indexExpEnd */) {
182 throw NonIntegerIndexableException(this, targetExpBegin, targetExpEnd);
183 }
184
indexedByString(intrusive_ptr<STRING>,const CharPointer & targetExpBegin,const CharPointer & targetExpEnd,const CharPointer &,const CharPointer &)185 intrusive_ptr<Value> RightValue::indexedByString(intrusive_ptr<STRING> /* index */, const CharPointer &targetExpBegin, const CharPointer &targetExpEnd, const CharPointer & /* indexExpBegin */, const CharPointer & /* indexExpEnd */) {
186 throw NonStringIndexableException(this, targetExpBegin, targetExpEnd);
187 }
188
indexedByString(intrusive_ptr<STRING> str,const CharPointer &,const CharPointer &,const CharPointer & indexExpBegin,const CharPointer & indexExpEnd)189 intrusive_ptr<Value> RECORD::indexedByString(intrusive_ptr<STRING> str, const CharPointer & /* targetExpBegin */, const CharPointer & /* targetExpEnd */, const CharPointer &indexExpBegin, const CharPointer &indexExpEnd) {
190 const intrusive_ptr<Value> v = this->getField(str->theString, indexExpBegin, indexExpBegin);
191 if (!v)
192 throw FieldNotFoundException(str->theString, indexExpBegin, indexExpEnd, this);
193 return v;
194 }
195
indexedByBigInt(intrusive_ptr<INT> N,const CharPointer &,const CharPointer &,const CharPointer & indexExpBegin,const CharPointer & indexExpEnd)196 intrusive_ptr<Value> LIST::indexedByBigInt(intrusive_ptr<INT> N, const CharPointer & /* targetExpBegin */, const CharPointer & /* targetExpEnd */, const CharPointer &indexExpBegin, const CharPointer &indexExpEnd) {
197 long l;
198 if (!IsConvertible(l, N->theBigInt) || l<=0 || static_cast<ContainerType::size_type>(l)>this->size())
199 throw IndexOutOfRangeException(N->theBigInt, this->size(), indexExpBegin, indexExpEnd);
200 return this->getValue(l-1);
201 }
202
indexedByBigInt(intrusive_ptr<INT> N,const CharPointer &,const CharPointer &,const CharPointer & indexExpBegin,const CharPointer & indexExpEnd)203 intrusive_ptr<Value> STRING::indexedByBigInt(intrusive_ptr<INT> N, const CharPointer & /* targetExpBegin */, const CharPointer & /* targetExpEnd */, const CharPointer &indexExpBegin, const CharPointer &indexExpEnd) {
204 long l;
205 if (!IsConvertible(l, N->theBigInt) || l<=0 || static_cast<string::size_type>(l)>this->theString.length())
206 throw IndexOutOfRangeException(N->theBigInt, this->theString.length(), indexExpBegin, indexExpEnd);
207 return new STRING(string(1, this->theString[l-1]));
208 }
209
indexedByBigInt(intrusive_ptr<INT> N,const CharPointer &,const CharPointer &,const CharPointer & indexExpBegin,const CharPointer & indexExpEnd)210 intrusive_ptr<Value> IntMapValue::indexedByBigInt(intrusive_ptr<INT> N, const CharPointer & /* targetExpBegin */, const CharPointer & /* targetExpEnd */, const CharPointer &indexExpBegin, const CharPointer &indexExpEnd) {
211 long l;
212 if (!IsConvertible(l, N->theBigInt))
213 throw RuntimeException("Index is not a machine-integer", indexExpBegin, indexExpEnd);
214 if (const intrusive_ptr<RightValue> result = this->getValue(l))
215 return result;
216 throw RuntimeException("Invalid index", indexExpBegin, indexExpEnd);
217 }
218
indexedByBigInt(intrusive_ptr<INT> N,const CharPointer &,const CharPointer &,const CharPointer & indexExpBegin,const CharPointer & indexExpEnd)219 intrusive_ptr<Value> MAT::indexedByBigInt(intrusive_ptr<INT> N, const CharPointer & /* targetExpBegin */, const CharPointer & /* targetExpEnd */, const CharPointer &indexExpBegin, const CharPointer &indexExpEnd) {
220 long l;
221 if (!IsConvertible(l, N->theBigInt))
222 throw RuntimeException("Index is not a machine-integer", indexExpBegin, indexExpEnd);
223 const size_t row = static_cast<size_t>(l);
224 if (l>=1 && row<=this->numRows()) // note: cannot use row>=1 because size_t is unsigned
225 return new MatrixRowValue(this, row-1);
226 throw RuntimeException("Invalid row index", indexExpBegin, indexExpEnd);
227 }
228
indexedByBigInt(intrusive_ptr<INT> N,const CharPointer &,const CharPointer &,const CharPointer & indexExpBegin,const CharPointer & indexExpEnd)229 intrusive_ptr<Value> MatrixRowValue::indexedByBigInt(intrusive_ptr<INT> N, const CharPointer & /* targetExpBegin */, const CharPointer & /* targetExpEnd */, const CharPointer &indexExpBegin, const CharPointer &indexExpEnd) {
230 long l;
231 if (!IsConvertible(l, N->theBigInt))
232 throw RuntimeException("Index is not a machine-integer", indexExpBegin, indexExpEnd);
233 const size_t col = static_cast<size_t>(l);
234 if (l>=1 && col<=this->matrix->numColumns()) // note: cannot use col>=1 because size_t is unsigned
235 return new RINGELEM(this->matrix->theMatrix(this->nRow, col-1));
236 throw RuntimeException("Invalid column index", indexExpBegin, indexExpEnd);
237 }
238
indexedByBigInt(intrusive_ptr<INT> N,const CharPointer &,const CharPointer &,const CharPointer & indexExpBegin,const CharPointer & indexExpEnd)239 intrusive_ptr<Value> MODULEELEM::indexedByBigInt(intrusive_ptr<INT> N, const CharPointer & /* targetExpBegin */, const CharPointer & /* targetExpEnd */, const CharPointer &indexExpBegin, const CharPointer &indexExpEnd) {
240 long l;
241 long nc = NumCompts(this->theModuleElem);
242 if (!IsConvertible(l, N->theBigInt) || l<=0 || l>nc)
243 throw IndexOutOfRangeException(N->theBigInt, nc, indexExpBegin, indexExpEnd);
244 return Value::from((this->theModuleElem)[l-1]);
245 }
246
IntegerIndexedAccess(const intrusive_ptr<LeftValue> targetLV,const BigInt & index,const CharPointer & targetExpBegin,const CharPointer & targetExpEnd,const CharPointer & indexExpBegin,const CharPointer & indexExpEnd)247 IntegerIndexedAccess::IntegerIndexedAccess(const intrusive_ptr<LeftValue> targetLV, const BigInt &index, const CharPointer &targetExpBegin, const CharPointer &targetExpEnd, const CharPointer &indexExpBegin, const CharPointer &indexExpEnd) :
248 IndexedAccess(targetLV, targetExpBegin, targetExpEnd, indexExpBegin, indexExpEnd),
249 index(index)
250 {
251 intrusive_ptr<RightValue> target = this->targetLV->asRightValue();
252 if (!target->canBeIndexedByBigInt())
253 throw NonIntegerIndexableException(target, targetExpBegin, targetExpEnd);
254 }
255
SnapshotFrame(const Frame & frame)256 SnapshotFrame::SnapshotFrame(const Frame &frame) :
257 invocationExp(frame.invocationExp),
258 block(frame.block)
259 {
260 assert(this->invocationExp);
261 assert(this->block);
262 }
263
RuntimeException(const string & reason,const CharPointer & from,const CharPointer & to,const Frame * const)264 RuntimeException::RuntimeException(const string &reason, const CharPointer &from, const CharPointer &to, const Frame * const) :
265 ExceptionWithSourcePosition(reason, from, to, false)
266 {}
267
RuntimeException(const string & reason,intrusive_ptr<const ParsedObject> po,const Frame * const)268 RuntimeException::RuntimeException(const string &reason, intrusive_ptr<const ParsedObject> po, const Frame * const) :
269 ExceptionWithSourcePosition(reason, po->getBegin(), po->getEnd(), false)
270 {}
271
RuntimeException(const string & reason,const Token & token,const Frame * const)272 RuntimeException::RuntimeException(const string &reason, const Token &token, const Frame * const) :
273 ExceptionWithSourcePosition(reason, token, false)
274 {}
275
PackageValue(const intrusive_ptr<const PackageStatement> pkgDecl)276 PackageValue::PackageValue(const intrusive_ptr<const PackageStatement> pkgDecl) :
277 pkgDecl(pkgDecl),
278 pkgName(pkgDecl->name),
279 prefix(pkgDecl->name+".")
280 {}
281
describe(intrusive_ptr<OSTREAM> out)282 void RightValue::describe(intrusive_ptr<OSTREAM> out) const {
283 out->print("A value of type ")->println(this->getType());
284 }
285
describe(intrusive_ptr<OSTREAM> out)286 void INT::describe(intrusive_ptr<OSTREAM> out) const {
287 if (this->theBigInt==BigInt(42))
288 out->println("The Answer to the Ultimate Question of Life, the Universe and Everything");
289 else
290 this->RightValue::describe(out);
291 }
292
describe(intrusive_ptr<OSTREAM> out)293 void RING::describe(intrusive_ptr<OSTREAM> out) const {
294 ostringstream os;
295 this->theRing->myOutputSelfLong(os);
296 out->print(os.str())->newline()->flush();
297 }
298
describe(intrusive_ptr<OSTREAM> out)299 void BuiltInFunction::describe(intrusive_ptr<OSTREAM> out) const {
300 out->println("A built-in function");
301 }
302
describe(intrusive_ptr<OSTREAM> out)303 void RINGHOM::describe(intrusive_ptr<OSTREAM> out) const {
304 out->println(this);
305 }
306
describe(intrusive_ptr<OSTREAM> out)307 void UserDefinedFunction::describe(intrusive_ptr<OSTREAM> out) const {
308 out->println(this->fnDecl->getBegin().stringTo(this->fnDecl->getEnd()));
309 }
310
describe(intrusive_ptr<OSTREAM> out)311 void PackageValue::describe(intrusive_ptr<OSTREAM> out) const
312 {
313 const intrusive_ptr<const PackageStatement> pkgDecl = this->pkgDecl;
314 const string &pkgName = pkgDecl->name;
315 if (this->pkgDecl->memberNames.empty())
316 {
317 out->print("The package ")->print(pkgName)->println(" is empty.\n");
318 return;
319 }
320 set<string> exports;
321 if (pkgDecl->exportedNames.empty())
322 { out->print("The package ")->print(pkgName)->print(" has no exported names.\n"); }
323 else
324 {
325 out->print("The package ")->print(pkgName)->print(" exports the following names:\n");
326 // Put names into a set so that they are printed in alphabetical order.
327 BOOST_FOREACH(const Token &t, pkgDecl->exportedNames)
328 exports.insert(t.lexeme());
329 BOOST_FOREACH(const string &s, exports)
330 out->print("* ")->println(s);
331 }
332 if (pkgDecl->memberNames.size() > exports.size())
333 {
334 out->print("\nThe package ")->print(pkgName)->print(" also has the following non-exported members:\n");
335 BOOST_FOREACH(const string &s, pkgDecl->memberNames)
336 if (exports.find(s) == exports.end()) // print s only if it not an export
337 out->print("* ")->print(pkgName)->print(".")->println(s);
338 }
339 }
340
OutputFileStreamValue(intrusive_ptr<STRING> filename,intrusive_ptr<const Expression> sourceExp)341 OutputFileStreamValue::OutputFileStreamValue(intrusive_ptr<STRING> filename, intrusive_ptr<const Expression> sourceExp) :
342 CppOSTREAM(stream, true, false),
343 stream(filename->theString.c_str())
344 {
345 if (!stream.is_open())
346 throw RuntimeException("Cannot open file \""+filename->theString+"\" for writing", sourceExp);
347 }
348
getOutputStream()349 intrusive_ptr<OSTREAM> RuntimeEnvironment::getOutputStream() {
350 return this->standardOutput;
351 }
352
TaggedValue(boost::intrusive_ptr<RightValue> value,const std::string & tag)353 TaggedValue::TaggedValue(boost::intrusive_ptr<RightValue> value, const std::string &tag) :
354 type(TYPE::tagType(tag)),
355 value(value),
356 tag(tag)
357 {}
358
359 map<string, intrusive_ptr<TYPE> > TYPE::taggedTypes;
360
tagType(const string & tag)361 intrusive_ptr<TYPE> TYPE::tagType(const string &tag) {
362 map<string, intrusive_ptr<TYPE> >::const_iterator it = taggedTypes.find(tag);
363 if (it!=taggedTypes.end())
364 return it->second;
365 intrusive_ptr<TYPE> newTaggedType(new TYPE("TAGGED(\""+tag+"\")", -1));
366 taggedTypes.insert(make_pair(tag, newTaggedType));
367 return newTaggedType;
368 }
369
dumpAsString(ostream & out)370 ostream &TYPE::dumpAsString(ostream &out) const {
371 return out << this->name;
372 }
373
dumpAsString(ostream & out)374 ostream &RINGELEM::dumpAsString(ostream &out) const {
375 return out << this->theRingElem;
376 }
377
dumpAsString(ostream & out)378 ostream &IDEAL::dumpAsString(ostream &out) const {
379 return out << this->theIdeal;
380 }
381
dumpAsString(ostream & out)382 ostream &MODULE::dumpAsString(ostream &out) const {
383 return out << this->theModule;
384 }
385
dumpAsString(ostream & out)386 ostream &MODULEELEM::dumpAsString(ostream &out) const {
387 return out << this->theModuleElem;
388 }
389
dumpAsString(ostream & out)390 ostream &RING::dumpAsString(ostream &out) const {
391 return out << this->theRing;
392 }
393
dumpAsString(ostream & out)394 ostream &IntMapValue::dumpAsString(ostream &out) const {
395 out << "{";
396 bool first=true;
397 for(MapType::const_iterator pos = this->map.begin(); pos!=this->map.end(); ++pos) {
398 if (first)
399 first = false;
400 else
401 out << ", ";
402 out << pos->first << " -> " << pos->second;
403 pos->second->dumpRefCountAsString(out);
404 }
405 return out << "}";
406 }
407
408 intrusive_ptr<TYPE> BOOL::type(new TYPE("BOOL", TYPE::DISPATCH_INDEX_OF_BOOL));
409 intrusive_ptr<TYPE> FUNCTION::type(new TYPE("FUNCTION", TYPE::DISPATCH_INDEX_OF_FUNCTION));
410 intrusive_ptr<TYPE> LIST::type(new TYPE("LIST", TYPE::DISPATCH_INDEX_OF_LIST));
411 intrusive_ptr<TYPE> INT::type(new TYPE("INT", TYPE::DISPATCH_INDEX_OF_BIGINT));
412 intrusive_ptr<TYPE> RAT::type(new TYPE("RAT", TYPE::DISPATCH_INDEX_OF_BIGRAT));
413 intrusive_ptr<TYPE> RECORD::type(new TYPE("RECORD", TYPE::DISPATCH_INDEX_OF_RECORD));
414 intrusive_ptr<TYPE> TYPE::type(new TYPE("TYPE", TYPE::DISPATCH_INDEX_OF_TYPE));
415 intrusive_ptr<TYPE> STRING::type(new TYPE("STRING", TYPE::DISPATCH_INDEX_OF_STRING));
416 intrusive_ptr<TYPE> VoidValue::type(new TYPE("VOID", TYPE::DISPATCH_INDEX_OF_VOID));
417 intrusive_ptr<TYPE> ERROR::type(new TYPE("ERROR", TYPE::DISPATCH_INDEX_OF_ERROR));
418 intrusive_ptr<TYPE> OSTREAM::type(new TYPE("OSTREAM", TYPE::DISPATCH_INDEX_OF_OSTREAM));
419 intrusive_ptr<TYPE> ISTREAM::type(new TYPE("ISTREAM", TYPE::DISPATCH_INDEX_OF_ISTREAM));
420 //JAA 20140901 intrusive_ptr<TYPE> ZZModValue::type(new TYPE("ZMOD", TYPE::DISPATCH_INDEX_OF_ZMOD));
421 intrusive_ptr<TYPE> RINGELEM::type(new TYPE("RINGELEM", TYPE::DISPATCH_INDEX_OF_RINGELEM));
422 intrusive_ptr<TYPE> RatFunValue::type(new TYPE("RATFUN", TYPE::DISPATCH_INDEX_OF_RATFUN));
423 intrusive_ptr<TYPE> IDEAL::type(new TYPE("IDEAL", TYPE::DISPATCH_INDEX_OF_IDEAL));
424 intrusive_ptr<TYPE> MODULE::type(new TYPE("MODULE", TYPE::DISPATCH_INDEX_OF_MODULE));
425 intrusive_ptr<TYPE> MODULEELEM::type(new TYPE("MODULEELEM", TYPE::DISPATCH_INDEX_OF_MODULEELEM));
426 intrusive_ptr<TYPE> MAT::type(new TYPE("MAT", TYPE::DISPATCH_INDEX_OF_MAT));
427 intrusive_ptr<TYPE> RING::type(new TYPE("RING", TYPE::DISPATCH_INDEX_OF_RING));
428 intrusive_ptr<TYPE> PackageValue::type(new TYPE("PACKAGE", TYPE::DISPATCH_INDEX_OF_PACKAGE));
429 intrusive_ptr<TYPE> IntMapValue::type(new TYPE("INTMAP", TYPE::DISPATCH_INDEX_OF_INTMAP));
430 intrusive_ptr<TYPE> RINGHOM::type(new TYPE("RINGHOM", TYPE::DISPATCH_INDEX_OF_RINGHOM));
431 intrusive_ptr<TYPE> MatrixRowValue::type(new TYPE("MATRIXROW", TYPE::DISPATCH_INDEX_OF_MATRIXROW));
432
433
getType()434 intrusive_ptr<TYPE> TaggedValue::getType() const {return this->type;}
getType()435 intrusive_ptr<TYPE> BOOL::getType() const {return type;}
getType()436 intrusive_ptr<TYPE> FUNCTION::getType() const {return type;}
getType()437 intrusive_ptr<TYPE> LIST::getType() const {return type;}
getType()438 intrusive_ptr<TYPE> INT::getType() const {return type;}
getType()439 intrusive_ptr<TYPE> RAT::getType() const {return type;}
getType()440 intrusive_ptr<TYPE> RECORD::getType() const {return type;}
getType()441 intrusive_ptr<TYPE> STRING::getType() const {return type;}
getType()442 intrusive_ptr<TYPE> VoidValue::getType() const {return type;}
getType()443 intrusive_ptr<TYPE> ERROR::getType() const {return type;}
getType()444 intrusive_ptr<TYPE> OSTREAM::getType() const {return type;}
getType()445 intrusive_ptr<TYPE> ISTREAM::getType() const {return type;}
getType()446 intrusive_ptr<TYPE> TYPE::getType() const {return type;}
getType()447 intrusive_ptr<TYPE> PackageValue::getType() const {return type;}
getType()448 intrusive_ptr<TYPE> RINGELEM::getType() const {return type;}
getType()449 intrusive_ptr<TYPE> IDEAL::getType() const {return type;}
getType()450 intrusive_ptr<TYPE> MODULE::getType() const {return type;}
getType()451 intrusive_ptr<TYPE> MODULEELEM::getType() const {return type;}
getType()452 intrusive_ptr<TYPE> RING::getType() const {return type;}
getType()453 intrusive_ptr<TYPE> IntMapValue::getType() const {return type;}
getType()454 intrusive_ptr<TYPE> RINGHOM::getType() const {return type;}
getType()455 intrusive_ptr<TYPE> MAT::getType() const {return type;}
getType()456 intrusive_ptr<TYPE> MatrixRowValue::getType() const {return type;}
457
allSymbolValues()458 vector<RING::SymbolPair> RING::allSymbolValues() {
459 vector<SymbolPair> result;
460 createAllSymbolValues(this->theRing, result);
461 return result;
462 }
463
createAllSymbolValues(const ring & R,std::vector<SymbolPair> & allIndets)464 void RING::createAllSymbolValues(const ring &R, std::vector<SymbolPair> &allIndets)
465 {
466 vector<symbol> syms;
467 if (IsPolyRing(R))
468 syms = symbols(CoeffRing(R));
469 else
470 syms = symbols(R);
471 BOOST_FOREACH(const symbol &s, syms)
472 allIndets.push_back(make_pair(s, new RINGELEM(RingElem(R, s))));
473 if (!IsPolyRing(R)) return;
474 const long nvars = NumIndets(R);
475 allIndets.reserve(allIndets.size() + nvars);
476 for (long i=0; i < nvars; ++i)
477 allIndets.push_back(make_pair(IndetSymbol(R,i), new RINGELEM(indet(R,i))));
478 }
479
removeInjectedIndeterminates(RuntimeEnvironment * runtimeEnv)480 void RING::removeInjectedIndeterminates(RuntimeEnvironment *runtimeEnv) {
481 Frame * const tlFrame = runtimeEnv->getTopLevelFrame();
482 BOOST_FOREACH(int slot, this->injectedSlots) {
483 VariableSlot &vs = tlFrame->varSlots[slot];
484 vs.value = 0;
485 vs.unprotect();
486 }
487 this->injectedSlots.clear();
488 }
489
injectIndeterminates(RuntimeEnvironment * runtimeEnv,const intrusive_ptr<const RingDefinition> ringDefinition,const string & ringName)490 void RING::injectIndeterminates(RuntimeEnvironment *runtimeEnv, const intrusive_ptr<const RingDefinition> ringDefinition, const string &ringName) {
491 assert(this->injectedSlots.empty());
492 string protectedNames, msgPrefix, msgSuffix;
493 Frame * const tlFrame = runtimeEnv->getTopLevelFrame();
494 vector<SymbolPair> allIndets(this->allSymbolValues());
495 BOOST_FOREACH(const SymbolPair &pair, allIndets) {
496 const symbol &sym = pair.first;
497 const string hd = head(sym);
498 if (hd==ringName)
499 runtimeEnv->interpreter->errorReporter->reportWarning("The name of an indeterminate corresponds to the name of the ring", ringDefinition->getBegin(), ringDefinition->getEnd(), WS_NORMAL);
500 const int slot = runtimeEnv->slotFor(hd);
501 if (slot<0)
502 continue;
503 if (tlFrame->varSlots[slot].isProtected()) {
504 if (protectedNames.length()==0) {
505 protectedNames = hd;
506 msgPrefix = " ";
507 msgSuffix = " is ";
508 } else {
509 protectedNames += ", ";
510 protectedNames += hd;
511 msgPrefix = "s ";
512 msgSuffix = " are ";
513 }
514 }
515 }
516 if (protectedNames.length())
517 throw RuntimeException("Cannot use the ring because the name"+msgPrefix+protectedNames+msgSuffix+"protected", ringDefinition);
518 int indetIndex=0;
519 map<string, intrusive_ptr<IntMapValue> > head2map;
520 BOOST_FOREACH(const SymbolPair &pair, allIndets) {
521 const symbol &sym = pair.first;
522 const int nSubscripts = NumSubscripts(sym);
523 const intrusive_ptr<RINGELEM> indeterminate(pair.second);
524 const string hd(head(sym));
525 //cout << "sym=" << sym << ", hd=" << hd << ", nSubscripts = " << nSubscripts << ", indeterminate=" << indeterminate << endl;
526 if (nSubscripts==0)
527 this->injectedSlots.push_back(runtimeEnv->setTopLevelVar(hd, indeterminate, VariableSlot::VSF_SystemProtected));
528 else {
529 map<string, intrusive_ptr<IntMapValue> >::const_iterator it = head2map.find(hd);
530 intrusive_ptr<IntMapValue> map;
531 if (it==head2map.end()) {
532 map = new IntMapValue();
533 head2map.insert(make_pair(hd, map));
534 } else
535 map = it->second;
536 this->injectedSlots.push_back(runtimeEnv->setTopLevelVar(hd, map, VariableSlot::VSF_SystemProtected));
537 for(int a=0; a<(nSubscripts-1); ++a) {
538 IntMapValue::KeyType i = subscript(sym, a);
539 intrusive_ptr<IntMapValue> v = dynamic_pointer_cast<IntMapValue>(map->getValue(i));
540 if (!v) {
541 v = new IntMapValue();
542 map->addValue(i, v);
543 }
544 map = v;
545 }
546 map->addValue(subscript(sym, nSubscripts-1), indeterminate);
547 }
548 ++indetIndex;
549 }
550 }
551
552 namespace {
553 class FakeExpression : public Expression {
554 private:
555 const intrusive_ptr<RightValue> value;
implEval(RuntimeEnvironment *)556 intrusive_ptr<Value> implEval(RuntimeEnvironment *) const {
557 return this->value;
558 }
skipDebugging()559 bool skipDebugging() const {
560 return true;
561 }
562 public:
FakeExpression(const intrusive_ptr<RightValue> value,const CharPointer & beginSourcePosition,const CharPointer & endSourcePosition)563 explicit FakeExpression(const intrusive_ptr<RightValue> value, const CharPointer &beginSourcePosition, const CharPointer & endSourcePosition) :
564 Expression(beginSourcePosition, endSourcePosition),
565 value(value)
566 {}
isLeftValue()567 bool isLeftValue() const { return false; }
dumpAsString(ostream & out)568 ostream &dumpAsString(ostream &out) const { assert(false); return out; }
accept(ParsedObjectVisitor *)569 void accept(ParsedObjectVisitor *) { assert(false); }
570 };
571
572 }
573
unaryMinus(const CharPointer & opPosition,RuntimeEnvironment * const runtimeEnv)574 intrusive_ptr<RightValue> TaggedValue::unaryMinus(const CharPointer &opPosition, RuntimeEnvironment * const runtimeEnv) {
575 runtimeEnv->interpreter->reportWarning("Performing this operation requires an implicit untagging; use untagged() to avoid this warning", opPosition, opPosition);
576 return this->value->unaryMinus(opPosition, runtimeEnv);
577 }
578
clone()579 intrusive_ptr<RightValue> TaggedValue::clone() {
580 return new TaggedValue(this->value->clone(), this->tag);
581 }
582
dumpAsString(ostream & out)583 ostream &TaggedValue::dumpAsString(ostream &out) const {
584 out << "tagged(";
585 this->value->dumpAsString(out);
586 intrusive_ptr<STRING> s = new STRING(this->tag);
587 return out << ", " << s << ")";
588 }
589
dumpAsString(ostream & out)590 ostream &ERROR::dumpAsString(ostream &out) const {
591 out << "error(";
592 intrusive_ptr<STRING> s = new STRING(this->message);
593 return out << s << ")";
594 }
595
dumpAsString(ostream & out)596 ostream &OSTREAM::dumpAsString(ostream &out) const {
597 return out << "<out-stream>";
598 }
599
dumpAsString(ostream & out)600 ostream &ISTREAM::dumpAsString(ostream &out) const {
601 return out << "<in-stream>";
602 }
603
close(RuntimeEnvironment *,intrusive_ptr<const Expression> sourceExp)604 intrusive_ptr<RightValue> OSTREAM::close(RuntimeEnvironment *, intrusive_ptr<const Expression> sourceExp) {
605 if (!this->canBeClosed)
606 throw RuntimeException("This out-stream cannot be closed", sourceExp);
607 if (this->isClosed)
608 throw RuntimeException("This out-stream is already closed", sourceExp);
609 this->isClosed = true;
610 // we don't actually close anything here, because that's a subclass responsibility
611 return VoidValue::theInstance;
612 }
613
close(RuntimeEnvironment * runtimeEnv,intrusive_ptr<const Expression> sourceExp)614 intrusive_ptr<RightValue> OutputStringStreamValue::close(RuntimeEnvironment *runtimeEnv, intrusive_ptr<const Expression> sourceExp) {
615 OSTREAM::close(runtimeEnv, sourceExp);
616 return new STRING(this->ss.str());
617 }
618
close(RuntimeEnvironment * runtimeEnv,intrusive_ptr<const Expression> sourceExp)619 intrusive_ptr<RightValue> OutputFileStreamValue::close(RuntimeEnvironment *runtimeEnv, intrusive_ptr<const Expression> sourceExp) {
620 OSTREAM::close(runtimeEnv, sourceExp);
621 this->stream.close();
622 return VoidValue::theInstance;
623 }
624
InputStringStreamValue(boost::intrusive_ptr<STRING> str)625 InputStringStreamValue::InputStringStreamValue(boost::intrusive_ptr<STRING> str) :
626 CppISTREAM(ss, true, false),
627 str(str),
628 ss(str->theString)
629 {}
630
631
InputFileStreamValue(intrusive_ptr<STRING> filename,intrusive_ptr<const Expression> sourceExp)632 InputFileStreamValue::InputFileStreamValue(intrusive_ptr<STRING> filename, intrusive_ptr<const Expression> sourceExp) :
633 CppISTREAM(stream, true, false),
634 stream(filename->theString.c_str())
635 {
636 if (!stream.is_open())
637 throw RuntimeException("Cannot open file \""+filename->theString+"\" for reading", sourceExp);
638 }
639
close(RuntimeEnvironment * runtimeEnv,intrusive_ptr<const Expression> sourceExp)640 boost::intrusive_ptr<RightValue> InputFileStreamValue::close(RuntimeEnvironment *runtimeEnv, intrusive_ptr<const Expression> sourceExp)
641 {
642 ISTREAM::close(runtimeEnv, sourceExp);
643 this->stream.close();
644 return VoidValue::theInstance;
645 }
646
647
close(RuntimeEnvironment *,intrusive_ptr<const Expression> sourceExp)648 boost::intrusive_ptr<RightValue> ISTREAM::close(RuntimeEnvironment *, intrusive_ptr<const Expression> sourceExp) {
649 if (!this->canBeClosed)
650 throw RuntimeException("This in-stream cannot be closed", sourceExp);
651 if (this->isClosed)
652 throw RuntimeException("This in-stream is already closed", sourceExp);
653 this->isClosed = true;
654 // we don't actually close anything here, because that's a subclass responsibility
655 return VoidValue::theInstance;
656 }
657
658
print(const std::string & str)659 boost::intrusive_ptr<OSTREAM> OutputBoostSocketStreamValue::print(const std::string &str) { (*out) << str; return this; }
print(boost::intrusive_ptr<const RightValue> v)660 boost::intrusive_ptr<OSTREAM> OutputBoostSocketStreamValue::print(boost::intrusive_ptr<const RightValue> v) { (*out) << v; return this; }
newline()661 boost::intrusive_ptr<OSTREAM> OutputBoostSocketStreamValue::newline() { (*out) << '\n' << std::flush; return this; }
flush()662 void OutputBoostSocketStreamValue::flush() { out->flush(); }
663
664
665
666 namespace {
stripPkgName(const string & s)667 string stripPkgName(const string &s) {
668 string::size_type dotPos = s.find('.', 0);
669 assert(dotPos!=string::npos);
670 return s.substr(dotPos+1);
671 }
672
getPkgNameWithDot(const string & s)673 string getPkgNameWithDot(const string &s) {
674 static const string::size_type l = ParserNS::Parser::TopLevelPackageName.length();
675 if (s.substr(0, l)==ParserNS::Parser::TopLevelPackageName)
676 return "";
677 string::size_type dotPos = s.find('.', 0);
678 assert(dotPos!=string::npos);
679 return s.substr(0, dotPos+1);
680 }
681 }
682
printTaggedValue(RuntimeEnvironment * runtimeEnv,intrusive_ptr<TaggedValue> v,intrusive_ptr<OSTREAM> out,intrusive_ptr<const Expression> sourceExp)683 void printTaggedValue(RuntimeEnvironment *runtimeEnv, intrusive_ptr<TaggedValue> v, intrusive_ptr<OSTREAM> out, intrusive_ptr<const Expression> sourceExp) {
684 const string recordName(getPkgNameWithDot(v->tag)+"PrintTagged");
685 int slot = runtimeEnv->slotFor(recordName);
686 if (slot<0) {
687 runtimeEnv->interpreter->reportWarning("Cannot find \""+recordName+"\", so I'm implicitly untagging the value", sourceExp);
688 implicit_untagging:
689 out->print(runtimeEnv, v->untagged(), sourceExp);
690 return;
691 }
692 intrusive_ptr<RECORD> record = dynamic_pointer_cast<RECORD>(runtimeEnv->getTopLevelFrame()->varSlots[slot].value);
693 if (!record) {
694 runtimeEnv->interpreter->reportWarning("The variable \""+recordName+"\" is not a record, so I'm implicitly untagging the value", sourceExp);
695 goto implicit_untagging;
696 }
697 const string fieldName(stripPkgName(v->tag));
698 intrusive_ptr<RightValue> fieldValue = record->getFieldNoCheck(fieldName);
699 if (!fieldValue) {
700 runtimeEnv->interpreter->reportWarning("The variable \""+recordName+"\" does not contain a field named \""+fieldName+"\", so I'm implicitly untagging the value", sourceExp);
701 goto implicit_untagging;
702 }
703 intrusive_ptr<FUNCTION> printingFun = dynamic_pointer_cast<FUNCTION>(fieldValue);
704 const string funName(recordName+"."+fieldName);
705 if (!printingFun) {
706 runtimeEnv->interpreter->reportWarning(funName+" does not contain a function, so I'm implicitly untagging the value", sourceExp);
707 goto implicit_untagging;
708 }
709 if (!printingFun->canBeCalledWith(2)) {
710 runtimeEnv->interpreter->reportWarning("The function "+funName+" cannot receive two arguments, so I'm implicitly untagging the value", sourceExp);
711 goto implicit_untagging;
712 }
713 if (const intrusive_ptr<UserDefinedFunction> udf = dynamic_pointer_cast<UserDefinedFunction>(printingFun)) {
714 for(int a=0; a<=1; ++a)
715 if (udf->fnDecl->params[a].byRef) {
716 runtimeEnv->interpreter->reportWarning("The function "+funName+" expects a by-ref argument, so I'm implicitly untagging the value", sourceExp);
717 goto implicit_untagging;
718 }
719 }
720 vector<Argument> args;
721 args.push_back(Argument(false, new FakeExpression(out, sourceExp->getBegin(), sourceExp->getEnd()), true));
722 args.push_back(Argument(false, new FakeExpression(v->untagged(), sourceExp->getBegin(), sourceExp->getEnd()), true));
723 intrusive_ptr<InvocationExpression> fakeInvoke =
724 new InvocationExpression(
725 new FakeExpression(printingFun, sourceExp->getBegin(), sourceExp->getEnd()),
726 boost::shared_ptr<Token>(),
727 args,
728 sourceExp->getEnd(),
729 ""
730 );
731 intrusive_ptr<Value> retValue = fakeInvoke->eval(runtimeEnv);
732 if (!dynamic_pointer_cast<VoidValue>(retValue))
733 throw RuntimeException("Printing-procedures must not return any value", sourceExp);
734 }
735
print(RuntimeEnvironment * runtimeEnv,intrusive_ptr<RightValue> v,intrusive_ptr<const Expression> sourceExp)736 void OSTREAM::print(RuntimeEnvironment *runtimeEnv, intrusive_ptr<RightValue> v, intrusive_ptr<const Expression> sourceExp) {
737 if (this->isClosed)
738 throw RuntimeException("Cannot print to a closed out-stream", sourceExp);
739 if (const intrusive_ptr<STRING> s = dynamic_pointer_cast<STRING>(v))
740 this->print(s->theString);
741 else if (const intrusive_ptr<TaggedValue> tv = dynamic_pointer_cast<TaggedValue>(v))
742 printTaggedValue(runtimeEnv, tv, this, sourceExp);
743 else
744 this->print(v);
745 }
746
flush()747 void CppOSTREAM::flush() {
748 out.flush();
749 }
750
print(const string & s)751 intrusive_ptr<OSTREAM> CppOSTREAM::print(const string &s) {
752 this->out << s;
753 return this;
754 }
755
print(intrusive_ptr<const RightValue> v)756 intrusive_ptr<OSTREAM> CppOSTREAM::print(intrusive_ptr<const RightValue> v) {
757 this->out << v;
758 return this;
759 }
760
newline()761 intrusive_ptr<OSTREAM> CppOSTREAM::newline() {
762 this->out << endl;
763 return this;
764 }
765
766
getline()767 std::string CppISTREAM::getline()
768 {
769 if (!in) return "\n"; // THROWING CAUSES A CRASH: throw IOException("GetLine from closed <in-stream>");
770 string str;
771 std::getline(in, str);
772 return str;
773 }
774
775
needsToBeCopiedBeforeChanges()776 bool TaggedValue::needsToBeCopiedBeforeChanges() const {
777 return this->value->needsToBeCopiedBeforeChanges();
778 }
779
FramePointer(Frame * const frame)780 FramePointer::FramePointer(Frame *const frame) :
781 frame(frame),
782 id(frame ? frame->id : 0)
783 {
784 }
785
toCheckedPointer()786 Frame *FramePointer::toCheckedPointer() const {
787 #ifdef VERBOSE_RUNTIME_DEBUG
788 //cout << "toCheckedPointer this->frame=" << this->frame << endl;
789 //if (this->frame)
790 // cout << "expected id=" << this->id << ", found " << this->frame->id << endl;
791 #endif // #ifdef VERBOSE_RUNTIME_DEBUG
792 return this->frame ? (this->frame->id==this->id ? this->frame : nullptr) : nullptr;
793 }
794
toNonNullCheckedPointer(intrusive_ptr<const Identifier> expId)795 Frame *FramePointer::toNonNullCheckedPointer(intrusive_ptr<const Identifier> expId) const {
796 Frame *f = this->toCheckedPointer();
797 if (!f)
798 throw DeadEnviromentException(expId);
799 return f;
800 }
801
addEnvironmentForIterationVar(const string & identifier,const CharPointer & from,const CharPointer & to)802 intrusive_ptr<StaticEnv> CheckNamesVisitor::addEnvironmentForIterationVar(const string &identifier, const CharPointer &from, const CharPointer &to) {
803 StaticEnv::VarData vd = this->env->lookup(identifier);
804 if (vd.depth!=StaticEnv::IN_THE_WILD)
805 this->errorReporter->reportWarning("This name hides an outer one", from, to);
806 this->env = new StaticEnv(this->env);
807 this->env->add(identifier, 0, 0, true, false, false);
808 return this->env;
809 }
810
visit(IdInExpSuchThatExp & idInExpSuchThatExp)811 void CheckNamesVisitor::visit(IdInExpSuchThatExp &idInExpSuchThatExp) {
812 idInExpSuchThatExp.exp1->accept(this);
813 idInExpSuchThatExp.staticEnv = this->addEnvironmentForIterationVar(idInExpSuchThatExp.identifier, idInExpSuchThatExp.tokIdentifier.getBegin(), idInExpSuchThatExp.tokIdentifier.getEnd());
814 idInExpSuchThatExp.exp2->accept(this);
815 this->popEnv();
816 }
817
visit(ExpSuchThatIdInExpAndExp & expSuchThatIdInExpAndExp)818 void CheckNamesVisitor::visit(ExpSuchThatIdInExpAndExp &expSuchThatIdInExpAndExp) {
819 expSuchThatIdInExpAndExp.exp2->accept(this);
820 expSuchThatIdInExpAndExp.staticEnv = this->addEnvironmentForIterationVar(expSuchThatIdInExpAndExp.identifier, expSuchThatIdInExpAndExp.tokIdentifier.getBegin(), expSuchThatIdInExpAndExp.tokIdentifier.getEnd());
821 expSuchThatIdInExpAndExp.exp1->accept(this);
822 if (expSuchThatIdInExpAndExp.optionalExp3)
823 expSuchThatIdInExpAndExp.optionalExp3->accept(this);
824 this->popEnv();
825 }
826
visit(FieldAccessExpression & fieldAccessExp)827 void CheckNamesVisitor::visit(FieldAccessExpression &fieldAccessExp) {
828 if (const intrusive_ptr<Identifier> identifier = dynamic_pointer_cast<Identifier>(fieldAccessExp.targetExp)) {
829 StaticEnv::VarData vd = this->env->lookup(identifier->identifier);
830 if (vd.depth==StaticEnv::IN_THE_WILD) {
831 string alias;
832 if (this->aliases->lookup(identifier->identifier, alias)) {
833 identifier->identifier = alias;
834 assert(vd.index<0);
835 assert(!vd.isCapturedValue);
836 assert(!vd.isIterationVar);
837 assert(!vd.isImplictlyImported);
838 vd.depth = StaticEnv::TOP_LEVEL;
839 } else {
840 if (this->insideFunctions)
841 this->reportError(VariableNotFoundException::errorMessage(identifier->identifier, identifier->arity, this->env), identifier->getBegin(), identifier->getEnd());
842 else
843 vd.depth = StaticEnv::TOP_LEVEL; // outside fn-procs, anything goes...
844 }
845 } else {
846 string alias;
847 if (this->aliases->lookup(identifier->identifier, alias))
848 this->errorReporter->reportWarning("I'm using the local/imported variable here, but note that there is an alias, with the same name, for the package "+alias, identifier->getBegin(), identifier->getEnd(), WS_PEDANTIC);
849 }
850 identifier->varData = vd;
851 } else
852 fieldAccessExp.targetExp->accept(this);
853 }
854
visit(Identifier & identifier)855 void CheckNamesVisitor::visit(Identifier &identifier) {
856 StaticEnv::VarData vd = this->env->lookup(identifier.identifier);
857 if (vd.depth==StaticEnv::IN_THE_WILD) {
858 if (this->runtimeEnvironment->isRegisteredType(identifier.identifier))
859 vd.depth = StaticEnv::TOP_LEVEL;
860 else {
861 if (this->insideFunctions)
862 this->reportError(VariableNotFoundException::errorMessage(identifier.identifier, identifier.arity, this->env), identifier.getBegin(), identifier.getEnd());
863 else {
864 vd.depth = StaticEnv::TOP_LEVEL; // outside fn-procs, anything goes...
865 vd.isImplictlyImported = true; // this is important for non-fnproc package member declarations
866 }
867 }
868 }
869 identifier.varData = vd;
870 }
871
reportError(const string & msg,const CharPointer & from,const CharPointer & to)872 void CheckNamesVisitor::reportError(const string &msg, const CharPointer &from, const CharPointer &to) {
873 this->foundErrors = true;
874 this->errorReporter->reportError(msg, from, to);
875 }
876
visit(ForStatement & forStmt)877 void CheckNamesVisitor::visit(ForStatement &forStmt) {
878 forStmt.beginExp->accept(this);
879 if (forStmt.stepExp)
880 forStmt.stepExp->accept(this);
881 forStmt.endExp->accept(this);
882 forStmt.staticEnv = this->addEnvironmentForIterationVar(forStmt.identifier, forStmt.tokIdentifier.getBegin(), forStmt.tokIdentifier.getEnd());
883 forStmt.statements->accept(this);
884 this->popEnv();
885 }
886
visit(ForeachStatement & foreachStmt)887 void CheckNamesVisitor::visit(ForeachStatement &foreachStmt) {
888 foreachStmt.inExp->accept(this);
889 foreachStmt.staticEnv = this->addEnvironmentForIterationVar(foreachStmt.identifier, foreachStmt.tokIdentifier.getBegin(), foreachStmt.tokIdentifier.getEnd());
890 foreachStmt.statements->accept(this);
891 this->popEnv();
892 }
893
visit(TryStatement & tryStmt)894 void CheckNamesVisitor::visit(TryStatement &tryStmt) {
895 tryStmt.tryStatements->accept(this);
896 tryStmt.staticEnv = this->addEnvironmentForIterationVar(tryStmt.identifier, tryStmt.tokIdentifier.getBegin(), tryStmt.tokIdentifier.getEnd());
897 tryStmt.uponErrorStatements->accept(this);
898 this->popEnv();
899 }
900
visit(FunctionDeclaration & funDecl)901 void CheckNamesVisitor::visit(FunctionDeclaration &funDecl) {
902 bool oldInsideFunctions = this->insideFunctions;
903 this->insideFunctions = true;
904 funDecl.staticEnv = this->env = new StaticEnv(this->env);
905 BOOST_FOREACH(Import &i, funDecl.imports) {
906 StaticEnv::VarData vd = (i.type==Import::IT_BYVALUE ? this->env->parent : this->env)->lookup(i.name);
907 const int depth = vd.depth;
908 if (i.type==Import::IT_TOPLEVEL) {
909 if (i.implicit && depth>=0)
910 this->errorReporter->reportWarning("The name \""+i.name+"\" has been implicitly imported from TopLevel; note that importing the name by-ref could yield a different result (add an explicit import to avoid this message)", funDecl.getBegin(), funDecl.getEnd());
911 this->env->add(i.name, StaticEnv::TOP_LEVEL, -1, false, false, i.implicit);
912 continue;
913 }
914 if (depth==StaticEnv::IN_THE_WILD) {
915 assert(i.expId);
916 this->reportError("Cannot find "+i.name, i.expId->getBegin(), i.expId->getEnd());
917 continue;
918 }
919 if (i.type==Import::IT_BYVALUE) {
920 assert(i.expId);
921 i.expId->varData = vd;
922 assert(!i.implicit);
923 this->env->add(i.name, 0, i.byValueIndex, false, true, false);
924 } else {
925 assert(i.type==Import::IT_BYREF);
926 if (vd.isIterationVar) {
927 assert(i.expId);
928 this->reportError("Iteration variables cannot be imported by-ref", i.expId->getBegin(), i.expId->getEnd());
929 } if (vd.isCapturedValue) {
930 assert(i.expId);
931 this->reportError("Names imported by-value cannot be re-imported by-ref", i.expId->getBegin(), i.expId->getEnd());
932 } else {
933 assert(!i.implicit);
934 this->env->add(i.name, depth, vd.index, false, false, false);
935 }
936 }
937 }
938 for(map<string, int>::const_iterator it=funDecl.localNames.begin(); it!=funDecl.localNames.end(); ++it)
939 env->add(it->first, 0, it->second, false, false, false);
940 funDecl.statements->accept(this);
941 this->popEnv();
942 this->insideFunctions = oldInsideFunctions;
943 }
944
visit(InvocationExpression & invocationExp)945 void CheckNamesVisitor::visit(InvocationExpression &invocationExp) {
946 ParsedObjectVisitor::visit(invocationExp);
947 BOOST_FOREACH(const Argument &arg, invocationExp.args)
948 if (arg.byRef)
949 if (const intrusive_ptr<Identifier> id = dynamic_pointer_cast<Identifier>(arg.exp)) {
950 if (id->varData.isCapturedValue)
951 this->reportError("Cannot pass by-ref an imported by value", arg.exp->getBegin(), arg.exp->getEnd());
952 }
953 }
954
visit(AssignmentStatement & assignmentStmt)955 void CheckNamesVisitor::visit(AssignmentStatement &assignmentStmt) {
956 ParsedObjectVisitor::visit(assignmentStmt);
957 if (const intrusive_ptr<Identifier> id = dynamic_pointer_cast<Identifier>(assignmentStmt.leftExp)) {
958 if (id->varData.isCapturedValue)
959 this->reportError("Cannot assign to a variable imported by value", assignmentStmt.leftExp->getBegin(), assignmentStmt.leftExp->getEnd());
960 }
961 }
962
visit(DefineStatement & defineStmt)963 void CheckNamesVisitor::visit(DefineStatement &defineStmt) {
964 defineStmt.funDecl->accept(this);
965 }
966
visit(AliasStatement & aliasStmt)967 void CheckNamesVisitor::visit(AliasStatement &aliasStmt) {
968 assert(this->aliases);
969 //if (aliasStmt.statements)
970 // this->aliases = new AliasEnv(this->aliases);
971 BOOST_FOREACH(const Binding &b, aliasStmt.bindings) {
972 const string newAlias(b.identifier->identifier);
973 if ( /* aliasStmt.statements || */ this->insidePackage) {
974 string useless;
975 if (this->aliases->parent->lookup(newAlias, useless))
976 this->errorReporter->reportWarning("This alias hides an outer one", b.identifier->getBegin(), b.identifier->getEnd());
977 }
978 this->aliases->add(newAlias, b.packageName);
979 }
980 /* if (aliasStmt.statements) {
981 aliasStmt.statements->accept(this);
982 this->aliases = this->aliases->parent;
983 assert(this->aliases);
984 } */
985 }
986
visit(PackageStatement & p)987 void CheckNamesVisitor::visit(PackageStatement &p) {
988 assert(this->aliases);
989 this->insidePackage = true;
990 this->aliases = new AliasEnv(this->aliases);
991 p.statements->accept(this);
992 this->aliases = this->aliases->parent;
993 assert(this->aliases);
994 this->insidePackage = false;
995 }
996
visit(InvocationExpression & invocationExp)997 void ResolvePackageNamesVisitor::visit(InvocationExpression &invocationExp) {
998 const intrusive_ptr<Identifier> id = dynamic_pointer_cast<Identifier>(invocationExp.targetExp);
999 if (!id || !id->varData.isImplictlyImported || this->packageStatement.memberNames.find(id->identifier)==this->packageStatement.memberNames.end())
1000 invocationExp.targetExp->accept(this);
1001 else {
1002 StaticEnv::VarData &vd = id->varData;
1003 assert(vd.depth == StaticEnv::TOP_LEVEL);
1004 assert(!vd.isCapturedValue);
1005 assert(!vd.isIterationVar);
1006 id->identifier = this->packageStatement.name+"."+id->identifier;
1007 vd.isImplictlyImported = false;
1008 //cout << "\n\n### " << id << " --> " << invocationExp.targetExp << " ###\n\n";
1009 }
1010 BOOST_FOREACH(const Argument &arg, invocationExp.args)
1011 arg.exp->accept(this);
1012 }
1013
1014 namespace {
1015 // based on: http://www.merriampark.com/ld.htm and http://www.merriampark.com/ldcpp.htm
levenshteinDistance(string source,string target)1016 int levenshteinDistance(string source, string target) {
1017 const int n = source.length();
1018 const int m = target.length();
1019 if (n == 0)
1020 return m;
1021 if (m == 0)
1022 return n;
1023 to_lower(source);
1024 to_lower(target);
1025 vector<vector<int> > matrix(n+1);
1026 for (int i = 0; i <= n; ++i)
1027 matrix[i].resize(m+1);
1028 for (int i = 0; i <= n; ++i)
1029 matrix[i][0]=i;
1030 for (int j = 0; j <= m; ++j)
1031 matrix[0][j]=j;
1032 for (int i = 1; i <= n; ++i) {
1033 const char s_i = source[i-1];
1034 for (int j = 1; j <= m; ++j) {
1035 const char t_j = target[j-1];
1036 const int cost = s_i == t_j ? 0 : 1;
1037 const int above = matrix[i-1][j];
1038 const int left = matrix[i][j-1];
1039 const int diag = matrix[i-1][j-1];
1040 int cell = min(above + 1, min(left + 1, diag + cost));
1041 // Step 6A: Cover transposition, in addition to deletion,
1042 // insertion and substitution. This step is taken from:
1043 // Berghel, Hal ; Roach, David : "An Extension of Ukkonen's
1044 // Enhanced Dynamic Programming ASM Algorithm"
1045 // (http://www.acm.org/~hlb/publications/asm/asm.html)
1046 if (i>2 && j>2) {
1047 int trans=matrix[i-2][j-2]+1;
1048 if (source[i-2]!=t_j) ++trans;
1049 if (s_i!=target[j-2]) ++trans;
1050 if (cell>trans) cell=trans;
1051 }
1052 matrix[i][j]=cell;
1053 }
1054 }
1055 return matrix[n][m];
1056 }
1057
maximumDistanceForSimilarIdentifiers(const string & id)1058 inline int maximumDistanceForSimilarIdentifiers(const string &id) {
1059 const int len = id.length();
1060 assert(len>0);
1061 if (len<=1)
1062 return 0; // use only case-insensitivity when looking for one-char identifiers (otherwise all of them would be considered similar)
1063 return (len+3)/4; // allow 1-char diff for lengths 2,3,4; 2-char diff for lengths 5-8, etc.
1064 }
1065 }
1066
reportInterrupt(const CharPointer & from,const CharPointer & to)1067 void Interpreter::reportInterrupt(const CharPointer &from, const CharPointer &to) {
1068 this->errorReporter->reportInterrupt(from, to);
1069 }
1070
reportError(const string & msg)1071 void Interpreter::reportError(const string &msg) {
1072 this->errorReporter->reportError(msg);
1073 }
1074
reportError(const string & msg,const CharPointer & from,const CharPointer & to)1075 void Interpreter::reportError(const string &msg, const CharPointer &from, const CharPointer &to) {
1076 this->errorReporter->reportError(msg, from, to);
1077 }
1078
findStaticEnv()1079 intrusive_ptr<const StaticEnv> RuntimeEnvironment::findStaticEnv() {
1080 Frame *f = this->currentFrame;
1081 //JAA for(; f>this->frames; --f)
1082 for(; f>getTopLevelFrame(); --f)
1083 if (f->userdefinedFun) {
1084 assert(f->userdefinedFun->fnDecl);
1085 assert(f->userdefinedFun->fnDecl->staticEnv);
1086 return f->userdefinedFun->fnDecl->staticEnv;
1087 }
1088 return topLevelStaticEnv;
1089 }
1090
pushFrame(const FramePointer & accessLink,intrusive_ptr<const InvocationExpression> invocationExp,intrusive_ptr<const ParsedObject> block,intrusive_ptr<const UserDefinedFunction> userdefinedFun)1091 Frame *RuntimeEnvironment::pushFrame(const FramePointer &accessLink, intrusive_ptr<const InvocationExpression> invocationExp, intrusive_ptr<const ParsedObject> block, intrusive_ptr<const UserDefinedFunction> userdefinedFun) {
1092 assert(block);
1093 #ifdef VERBOSE_RUNTIME_DEBUG
1094 cout << "pushFrame for " << block << endl;
1095 #endif // #ifdef VERBOSE_RUNTIME_DEBUG
1096 if (this->currentFrame==&frames.back())
1097 throw RuntimeException("Too many nested scopes", invocationExp ? invocationExp : block);
1098 Frame * const f = ++this->currentFrame;
1099 f->id = ++this->nextFrameId;
1100 assert(f->id); // f->id==0 would mean we've just overflowed!
1101 f->accessLink = accessLink;
1102 f->invocationExp = invocationExp;
1103 f->block = block;
1104 f->userdefinedFun = userdefinedFun;
1105 #ifdef C5IDE
1106 f->singleStepOnPop = false;
1107 #endif // #ifdef C5IDE
1108 return f;
1109 }
1110
pushIterationFrame(intrusive_ptr<const ParsedObject> block)1111 Frame *RuntimeEnvironment::pushIterationFrame(intrusive_ptr<const ParsedObject> block) {
1112 assert(block);
1113 assert(block->staticEnv);
1114 Frame *f = this->pushFrame(this->currentFrame, 0, block, 0);
1115 this->currentFrame->varSlots.push_back(VariableSlot(VoidValue::theInstance, static_cast<VariableSlot::Flags>(VariableSlot::VSF_SystemProtected|VariableSlot::VSF_IterationVariable)));
1116 return f;
1117 }
1118
popFrame()1119 void RuntimeEnvironment::popFrame() {
1120 Frame * const f = this->currentFrame--;
1121 assert(f > getTopLevelFrame());
1122 #ifdef C5IDE
1123 if (f->singleStepOnPop)
1124 this->interpreter->singleStepExecution = true;
1125 #endif // #ifdef C5IDE
1126 f->id = 0;
1127 f->accessLink.reset();
1128 f->varSlots.clear();
1129 f->invocationExp = nullptr;
1130 f->block = nullptr;
1131 f->userdefinedFun = nullptr;
1132 #ifdef VERBOSE_RUNTIME_DEBUG
1133 if (this->currentFrame==&frames.back())
1134 cout << "popFrame, back to global\n";
1135 else
1136 cout << "popFrame, back to: " << this->currentFrame->block << endl;
1137 #endif // #ifdef VERBOSE_RUNTIME_DEBUG
1138 }
1139
takeSnapshot()1140 vector<SnapshotFrame> RuntimeEnvironment::takeSnapshot() {
1141 vector<SnapshotFrame> result;
1142 const Frame *f = this->currentFrame;
1143 do {
1144 if (f->invocationExp) {
1145 result.push_back(SnapshotFrame(*f));
1146 }
1147 } while (--f != getTopLevelFrame());
1148 return result;
1149 }
1150
registerType(intrusive_ptr<TYPE> type)1151 void RuntimeEnvironment::registerType(intrusive_ptr<TYPE> type) {
1152 #ifndef NDEBUG
1153 bool inserted =
1154 #endif
1155 this->registeredTypeNames.insert(type->name).second;
1156 assert(inserted);
1157 this->setTopLevelVar(type->name, type, VariableSlot::VSF_SystemProtected);
1158 }
1159
currentTypes()1160 intrusive_ptr<LIST> RuntimeEnvironment::currentTypes() {
1161 intrusive_ptr<LIST> result(new LIST);
1162 BOOST_FOREACH(const string &s, this->registeredTypeNames) {
1163 const int slot = this->slotFor(s);
1164 assert(slot>=0 && static_cast<vector<VariableSlot>::size_type>(slot)<getTopLevelFrame()->varSlots.size());
1165 result->addValue(intrusive_ptr_cast<TYPE>(getTopLevelFrame()->varSlots[slot].value));
1166 }
1167 typedef pair<string, intrusive_ptr<TYPE> > pair;
1168 BOOST_FOREACH(const pair &p, TYPE::taggedTypes)
1169 result->addValue(p.second);
1170 return result;
1171 }
1172
RuntimeEnvironment(Interpreter * const interpreter,intrusive_ptr<OSTREAM> standardOutput,long MaxStackSize)1173 RuntimeEnvironment::RuntimeEnvironment(Interpreter * const interpreter, intrusive_ptr<OSTREAM> standardOutput, long MaxStackSize) :
1174 frames(MaxStackSize),
1175 currentFrame(&(this->frames[0])),
1176 nextFrameId(1),
1177 standardOutput(standardOutput),
1178 topLevelStaticEnv(new StaticEnv(this)),
1179 topLevelAliases(new AliasEnv(0)),
1180 itSlot(this->setTopLevelVar(Interpreter::IT, VoidValue::theInstance, VariableSlot::VSF_SystemProtected)),
1181 currentRingSlot(this->setTopLevelVar(Interpreter::CURRENT_RING, VoidValue::theInstance, VariableSlot::VSF_SystemProtected)),
1182 interpreter(interpreter)
1183 {
1184 this->initBuiltInFunctions();
1185 this->registerType(BOOL::type);
1186 this->registerType(FUNCTION::type);
1187 this->registerType(LIST::type);
1188 this->registerType(INT::type);
1189 this->registerType(RAT::type);
1190 this->registerType(RECORD::type);
1191 this->registerType(TYPE::type);
1192 this->registerType(STRING::type);
1193 this->registerType(VoidValue::type);
1194 this->registerType(ERROR::type);
1195 this->registerType(OSTREAM::type);
1196 this->registerType(ISTREAM::type);
1197 //JAA 20140901 this->registerType(ZZModValue::type);
1198 this->registerType(RINGELEM::type);
1199 this->registerType(RatFunValue::type);
1200 this->registerType(IDEAL::type);
1201 this->registerType(MODULE::type);
1202 this->registerType(MODULEELEM::type);
1203 this->registerType(MAT::type);
1204 this->registerType(RING::type);
1205 this->registerType(IntMapValue::type);
1206 this->registerType(RINGHOM::type);
1207 this->registerType(MatrixRowValue::type);
1208 this->setTopLevelVar("ZZ", new RING(RingZZ()), VariableSlot::VSF_SystemProtected);
1209 this->setTopLevelVar("QQ", new RING(RingQQ()), VariableSlot::VSF_SystemProtected);
1210 this->setTopLevelVar("R", new RING(NewPolyRing(RingQQ(),symbols("x,y,z"))), VariableSlot::VSF_None);
1211 this->initMaps();
1212 }
1213
topLevelFunctions()1214 intrusive_ptr<LIST> RuntimeEnvironment::topLevelFunctions() {
1215 intrusive_ptr<LIST> result(new LIST);
1216 for(map<string, int>::const_iterator it = this->topLevelIdentifiers.begin(); it!=this->topLevelIdentifiers.end(); ++it) {
1217 assert(it->first.length());
1218 assert(it->second>=0 && it->second<static_cast<int>(getTopLevelFrame()->varSlots.size()));
1219 const VariableSlot &vslot = getTopLevelFrame()->varSlots[it->second];
1220 if (intrusive_ptr<FUNCTION> f = dynamic_pointer_cast<FUNCTION>(vslot.value)) {
1221 intrusive_ptr<RECORD> record(new RECORD);
1222 result->addValue(record);
1223 record->setFieldNoCheck("name", new STRING(it->first));
1224 record->setFieldNoCheck("IsExported", Value::from(vslot.hasBeenExported()));
1225 }
1226 }
1227 return result;
1228 }
1229
ResizeStack(long NewSize,const boost::intrusive_ptr<const AST::Expression> OrigExp)1230 long RuntimeEnvironment::ResizeStack(long NewSize, const boost::intrusive_ptr<const AST::Expression> OrigExp)
1231 {
1232 if (NewSize < 2)
1233 throw RuntimeException("Ridiculous stack size", OrigExp);
1234 const long CurrStackHeight = 1+(currentFrame-&frames[0]);
1235 if (CurrStackHeight >= NewSize)
1236 throw RuntimeException("Stack size too small", OrigExp);
1237 frames.resize(NewSize);
1238 return CurrStackHeight;
1239 }
1240
slotFor(const string & id)1241 int RuntimeEnvironment::slotFor(const string &id) {
1242 map<string, int>::const_iterator i=this->topLevelIdentifiers.find(id);
1243 return i!=this->topLevelIdentifiers.end() ? i->second : -1;
1244 }
1245
setTopLevelVar(const string & id,intrusive_ptr<Value> v,VariableSlot::Flags flags)1246 int RuntimeEnvironment::setTopLevelVar(const string &id, intrusive_ptr<Value> v, VariableSlot::Flags flags) {
1247 const int slot = this->slotFor(id);
1248 if (slot>=0) {
1249 VariableSlot &vs = this->frames[0].varSlots[slot];
1250 vs.value = v;
1251 vs.flags = flags;
1252 return slot;
1253 }
1254 const int newSlot = this->frames[0].varSlots.size();
1255 this->frames[0].varSlots.push_back(VariableSlot(v, flags));
1256 this->topLevelIdentifiers.insert(make_pair(id, newSlot));
1257 return newSlot;
1258 }
1259
Interpreter(bool warnAboutCocoa5,intrusive_ptr<LineProvider> lineProvider,intrusive_ptr<ErrorReporter> errorReporter,intrusive_ptr<OSTREAM> standardOutput,bool fullCoCoALibError,long MaxStackSize)1260 Interpreter::Interpreter(bool warnAboutCocoa5, intrusive_ptr<LineProvider> lineProvider, intrusive_ptr<ErrorReporter> errorReporter, intrusive_ptr<OSTREAM> standardOutput, /* intrusive_ptr<ISTREAM> standardInput,*/ bool fullCoCoALibError, long MaxStackSize) :
1261 warnAboutCocoa5(warnAboutCocoa5),
1262 fullCoCoALibError(fullCoCoALibError),
1263 lineProvider(lineProvider),
1264 runtimeEnvironment(this, standardOutput, MaxStackSize),
1265 //// controlC(false),
1266 #ifdef C5IDE
1267 singleStepExecution(false),
1268 doStepOver(false),
1269 #endif // #ifdef C5IDE
1270 errorReporter(errorReporter)
1271 #ifdef C5IDE
1272 , status(IS_WAITING_FOR_COMMAND) // while not 100% true (the call to this->run() will make this happen), it's a safe initialization value
1273 #endif // #ifdef C5IDE
1274 {
1275 assert(this->lineProvider);
1276 assert(this->errorReporter);
1277 }
1278
errorMessage(const string & varName,int arity,intrusive_ptr<const StaticEnv> env)1279 string VariableNotFoundException::errorMessage(const string &varName, int arity, intrusive_ptr<const StaticEnv> env) {
1280 string message("Cannot find a variable named \"");
1281 message += varName;
1282 message += "\" in scope";
1283 vector<string> NearMatches;
1284 bool thereIsAnExactMatch=false;
1285 env->collectSimilarlyNamedIdentifiers(varName, arity, NearMatches, thereIsAnExactMatch);
1286 if (thereIsAnExactMatch)
1287 return message+", but there is one in an outside scope. You're probably missing an import statement";
1288 const int size = NearMatches.size();
1289 if (size==0)
1290 return message;
1291 if (size==1) {
1292 message += ".\nA similarly named variable (that you might need to import) is: \"";
1293 message += NearMatches.front();
1294 message += '\"';
1295 return message;
1296 }
1297 message += ".\nSimilarly named variables (that you might need to import) are: ";
1298 bool first = true;
1299 BOOST_FOREACH(const string &id, NearMatches) {
1300 if (first)
1301 first = false;
1302 else
1303 message += ", ";
1304 message += '\"';
1305 message += id;
1306 message += '\"';
1307 }
1308 return message;
1309 }
1310
collectSimilarlyNamedFields(const string & fieldName,set<string> & set)1311 void RECORD::collectSimilarlyNamedFields(const string &fieldName, set<string> &set) const {
1312 const int maxDistance = maximumDistanceForSimilarIdentifiers(fieldName);
1313 for(MapType::const_iterator pos = this->fields.begin(); pos!=this->fields.end(); ++pos)
1314 if (levenshteinDistance(fieldName, pos->first)<=maxDistance)
1315 set.insert(pos->first);
1316 }
1317
myFieldNamesStrings()1318 vector<string> RECORD::myFieldNamesStrings() const {
1319 vector<string> result;
1320 for(MapType::const_iterator pos = this->fields.begin(); pos!=this->fields.end(); ++pos)
1321 result.push_back(pos->first);
1322 return result;
1323 }
1324
fieldNames()1325 intrusive_ptr<LIST> RECORD::fieldNames() const {
1326 intrusive_ptr<LIST> result(new LIST);
1327 for(MapType::const_iterator pos = this->fields.begin(); pos!=this->fields.end(); ++pos)
1328 result->addValue(new STRING(pos->first));
1329 return result;
1330 }
1331
errorMessage(const string & fieldName,intrusive_ptr<const RECORD> rv)1332 string FieldNotFoundException::errorMessage(const string &fieldName, intrusive_ptr<const RECORD> rv) {
1333 string message("Cannot find a field named \"");
1334 message += fieldName;
1335 message += '\"';
1336 if (rv->numberOfFields()==0)
1337 message += ". Note: the record is actually empty; that is, it has no fields at all";
1338 else {
1339 set<string> s;
1340 rv->collectSimilarlyNamedFields(fieldName, s);
1341 const int size = s.size();
1342 if (size==0)
1343 return message;
1344 if (size==1) {
1345 message += ".\nA similarly named (existing) field is: \"";
1346 message += *s.begin();
1347 message += '\"';
1348 return message;
1349 }
1350 message += ".\nSimilarly named (existing) fields are: ";
1351 bool first = true;
1352 BOOST_FOREACH(const string &id, s) {
1353 if (first)
1354 first = false;
1355 else
1356 message += ", ";
1357 message += '\"';
1358 message += id;
1359 message += '\"';
1360 }
1361 }
1362 return message;
1363 }
1364
reportWarning(const string & msg,const intrusive_ptr<const ParsedObject> po)1365 void Interpreter::reportWarning(const string &msg, const intrusive_ptr<const ParsedObject> po) {
1366 this->errorReporter->reportWarning(msg, po->getBegin(), po->getEnd());
1367 }
1368
reportWarning(const string & msg,const CharPointer & from,const CharPointer & to)1369 void Interpreter::reportWarning(const string &msg, const CharPointer &from, const CharPointer &to) {
1370 this->errorReporter->reportWarning(msg, from, to);
1371 }
1372
evalArg(const Argument & arg,EvalKind evalKind)1373 intrusive_ptr<Value> RuntimeEnvironment::evalArg(const Argument &arg, EvalKind evalKind) {
1374 const bool byRef = evalKind==EVAL_BY_REF;
1375 if (arg.byRef && !byRef)
1376 throw CorrespondingParameterNotReferenceException(arg.exp);
1377 intrusive_ptr<Value> v;
1378 if (byRef) {
1379 if (!arg.byRef && !arg.synthetized)
1380 this->interpreter->reportWarning("You should use \"ref\" when passing arguments by reference", arg.exp);
1381 v = arg.exp->eval(this);
1382 if (!dynamic_pointer_cast<LeftValue>(v))
1383 throw RuntimeException("Only left-values can be passed by reference", arg.exp);
1384 } else
1385 v = arg.exp->evalAs<RightValue>(this);
1386 return v;
1387 }
1388
1389 const string Interpreter::IT("It");
1390 const string Interpreter::CURRENT_RING("CurrentRing");
1391
1392 namespace // anonymous
1393 {
1394
checkProtection(VariableSlot * vs,const intrusive_ptr<const Identifier> id)1395 void checkProtection(VariableSlot *vs, const intrusive_ptr<const Identifier> id)
1396 {
1397 const string& name = id->identifier;
1398 if (vs->isProtected())
1399 {
1400 const string& reason(vs->getProtectionReason());
1401 if (!reason.empty())
1402 throw ProtectedVariableException(name, "Cannot set \""+name+"\" (protected: "+reason+")", id);
1403 if (vs->isSystemProtected())
1404 throw ProtectedVariableException(name, "Cannot set \""+name+"\" (system-protected variable)", id);
1405 throw ProtectedVariableException(name, "Cannot set \""+name+"\" (user-protected variable)", id);
1406 }
1407 if (vs->isPackage())
1408 {
1409 throw ProtectedVariableException(name, "Cannot set \""+name+"\" (package-exported variable)", id);
1410 }
1411 }
1412
1413 } // end of anonymous namespace
1414
isProperSubtypeOf(int otherDI)1415 bool TYPE::isProperSubtypeOf(int otherDI) const {
1416 switch (this->dispatchIndex) {
1417 case DISPATCH_INDEX_OF_BIGRAT:
1418 return otherDI==DISPATCH_INDEX_OF_RINGELEM;
1419 case DISPATCH_INDEX_OF_BIGINT:
1420 return otherDI==DISPATCH_INDEX_OF_BIGRAT || otherDI==DISPATCH_INDEX_OF_RINGELEM;
1421 case DISPATCH_INDEX_OF_RINGHOM:
1422 return otherDI==DISPATCH_INDEX_OF_FUNCTION;
1423 case DISPATCH_INDEX_OF_RECORD:
1424 case DISPATCH_INDEX_OF_BOOL:
1425 case DISPATCH_INDEX_OF_VOID:
1426 case DISPATCH_INDEX_OF_STRING:
1427 case DISPATCH_INDEX_OF_LIST:
1428 case DISPATCH_INDEX_OF_FUNCTION:
1429 case DISPATCH_INDEX_OF_TYPE:
1430 case DISPATCH_INDEX_OF_ERROR:
1431 case DISPATCH_INDEX_OF_OSTREAM:
1432 case DISPATCH_INDEX_OF_ISTREAM:
1433 //JAA 20140901 case DISPATCH_INDEX_OF_ZMOD:
1434 case DISPATCH_INDEX_OF_RATFUN:
1435 case DISPATCH_INDEX_OF_MODULEELEM:
1436 case DISPATCH_INDEX_OF_IDEAL:
1437 case DISPATCH_INDEX_OF_MODULE:
1438 case DISPATCH_INDEX_OF_MAT:
1439 case DISPATCH_INDEX_OF_RING:
1440 case DISPATCH_INDEX_OF_PACKAGE:
1441 case DISPATCH_INDEX_OF_RINGELEM:
1442 case DISPATCH_INDEX_OF_INTMAP:
1443 case DISPATCH_INDEX_OF_MATRIXROW:
1444 return false;
1445 default:
1446 assert(false);
1447 }
1448 return false;
1449 }
1450
convert(intrusive_ptr<const RightValue> from,intrusive_ptr<const RightValue> to)1451 intrusive_ptr<const RightValue> TYPE::convert(intrusive_ptr<const RightValue> from, intrusive_ptr<const RightValue> to) {
1452 assert(from);
1453 assert(to);
1454 assert(from->getType()->isProperSubtypeOf(to->getType()->dispatchIndex));
1455 switch (to->getType()->dispatchIndex) {
1456 case DISPATCH_INDEX_OF_BIGRAT:
1457 return new RAT(BigRat(intrusive_ptr_cast<const INT>(from)->theBigInt,1));
1458 case DISPATCH_INDEX_OF_RINGELEM:
1459 if (from->getType()->dispatchIndex==DISPATCH_INDEX_OF_BIGINT)
1460 return new RINGELEM(RingElem(owner(intrusive_ptr_cast<const RINGELEM>(to)->theRingElem), intrusive_ptr_cast<const INT>(from)->theBigInt));
1461 return new RINGELEM(RingElem(owner(intrusive_ptr_cast<const RINGELEM>(to)->theRingElem), intrusive_ptr_cast<const RAT>(from)->theBigRat));
1462 case DISPATCH_INDEX_OF_FUNCTION:
1463 return from;
1464 }
1465 assert(false);
1466 return nullptr;
1467 }
1468
1469
binaryOperatorDispatch(intrusive_ptr<const RightValue> leftOp,intrusive_ptr<const RightValue> rightOp,DispatchMapType map,const LexerNS::CharPointer & beginOperatorSourcePosition,const LexerNS::CharPointer & endOperatorSourcePosition)1470 intrusive_ptr<RightValue> RuntimeEnvironment::binaryOperatorDispatch(intrusive_ptr<const RightValue> leftOp, intrusive_ptr<const RightValue> rightOp, DispatchMapType map, const LexerNS::CharPointer &beginOperatorSourcePosition, const LexerNS::CharPointer &endOperatorSourcePosition)
1471 {
1472 this->interpreter->checkForInterrupts(beginOperatorSourcePosition, endOperatorSourcePosition);
1473 const intrusive_ptr<const TYPE> leftType(leftOp->getType());
1474 assert(leftType);
1475 int leftIndex = leftType->dispatchIndex;
1476 if (leftIndex<0)
1477 {
1478 const intrusive_ptr<const TaggedValue> tv = dynamic_pointer_cast<const TaggedValue>(leftOp);
1479 assert(tv);
1480 this->interpreter->reportWarning("I'm implicitly untagging the left operand; use untagged() to avoid this warning", beginOperatorSourcePosition, endOperatorSourcePosition);
1481 leftOp = tv->untagged();
1482 leftIndex = leftOp->getType()->dispatchIndex;
1483 }
1484 assert(leftIndex>=0 && leftIndex<TYPE::NUM_OF_DISPATCHABLE_TYPES);
1485 const intrusive_ptr<const TYPE> rightType(rightOp->getType());
1486 assert(rightType);
1487 int rightIndex = rightType->dispatchIndex;
1488 if (rightIndex<0)
1489 {
1490 const intrusive_ptr<const TaggedValue> tv = dynamic_pointer_cast<const TaggedValue>(rightOp);
1491 assert(tv);
1492 this->interpreter->reportWarning("I'm implicitly untagging the right operand; use untagged() to avoid this warning", beginOperatorSourcePosition, endOperatorSourcePosition);
1493 rightOp = tv->untagged();
1494 rightIndex = rightOp->getType()->dispatchIndex;
1495 }
1496 assert(rightIndex>=0 && rightIndex<TYPE::NUM_OF_DISPATCHABLE_TYPES);
1497 for(;;)
1498 {
1499 BinaryOpFunc f = map[leftIndex][rightIndex];
1500 if (f)
1501 try
1502 {
1503 return f(this, leftOp, rightOp, beginOperatorSourcePosition, endOperatorSourcePosition);
1504 }
1505 catch (const ErrorInfo& err)
1506 {
1507 this->announceCLE(err);
1508 throw RuntimeException(message_forC5(err), beginOperatorSourcePosition, endOperatorSourcePosition);
1509 }
1510 catch (const InterruptReceived& intr)
1511 {
1512 throw InterruptException(beginOperatorSourcePosition, endOperatorSourcePosition);
1513 }
1514 if (leftType->isProperSubtypeOf(rightIndex) && map[rightIndex][rightIndex])
1515 {
1516 try
1517 {
1518 leftOp = TYPE::convert(leftOp, rightOp);
1519 }
1520 catch (const ErrorInfo& err)
1521 {
1522 this->announceCLE(err);
1523 throw RuntimeException(message_forC5(err), beginOperatorSourcePosition, endOperatorSourcePosition);
1524 }
1525 catch (const InterruptReceived& /*intr*/)
1526 {
1527 throw InterruptException(beginOperatorSourcePosition, endOperatorSourcePosition);
1528 }
1529
1530 assert(leftOp->getType()->dispatchIndex == rightIndex);
1531 leftIndex = rightIndex;
1532 continue;
1533 }
1534 if (rightType->isProperSubtypeOf(leftIndex) && map[leftIndex][leftIndex])
1535 {
1536 try
1537 {
1538 rightOp = TYPE::convert(rightOp, leftOp);
1539 }
1540 catch (const ErrorInfo& err)
1541 {
1542 this->announceCLE(err);
1543 throw RuntimeException(message_forC5(err), beginOperatorSourcePosition, endOperatorSourcePosition);
1544 }
1545 catch (const InterruptReceived& /*intr*/)
1546 {
1547 throw InterruptException(beginOperatorSourcePosition, endOperatorSourcePosition);
1548 }
1549
1550 assert(rightOp->getType()->dispatchIndex == leftIndex);
1551 rightIndex = leftIndex;
1552 continue;
1553 }
1554 const string leftType = leftOp->getType()->name;
1555 const string rightType = rightOp->getType()->name;
1556 throw RuntimeException("I don't know how to evaluate operator "+beginOperatorSourcePosition.stringTo(endOperatorSourcePosition)+" between "+leftType+" and "+rightType, beginOperatorSourcePosition, endOperatorSourcePosition);
1557 }
1558 }
1559
announceCLE(const ErrorInfo & err)1560 void RuntimeEnvironment::announceCLE(const ErrorInfo& err) {
1561 if (this->interpreter->fullCoCoALibError) {
1562 ostringstream os;
1563 ANNOUNCE(os, err);
1564 this->standardOutput->print(os.str());
1565 }
1566 }
1567
1568 //----- operators ==, !=, <, >, <=, >=, +, -, *, / -----------------------
1569 // template functions for implementation in CoCoALib
1570
1571 template<typename LeftType, typename RightType>
opEqual(RuntimeEnvironment *,const intrusive_ptr<const RightValue> LeftTypeOp,const intrusive_ptr<const RightValue> RightTypeOp,const CharPointer &,const CharPointer &)1572 intrusive_ptr<RightValue> opEqual(RuntimeEnvironment *, const intrusive_ptr<const RightValue> LeftTypeOp, const intrusive_ptr<const RightValue> RightTypeOp, const CharPointer &, const CharPointer &) {
1573 return Value::from(theValue(intrusive_ptr_cast<const LeftType>(LeftTypeOp)) == theValue(intrusive_ptr_cast<const RightType>(RightTypeOp)));
1574 }
1575
1576 template<typename LeftType, typename RightType>
opNotEqual(RuntimeEnvironment *,const intrusive_ptr<const RightValue> LeftTypeOp,const intrusive_ptr<const RightValue> RightTypeOp,const CharPointer &,const CharPointer &)1577 intrusive_ptr<RightValue> opNotEqual(RuntimeEnvironment *, const intrusive_ptr<const RightValue> LeftTypeOp, const intrusive_ptr<const RightValue> RightTypeOp, const CharPointer &, const CharPointer &) {
1578 return Value::from(theValue(intrusive_ptr_cast<const LeftType>(LeftTypeOp)) != theValue(intrusive_ptr_cast<const RightType>(RightTypeOp)));
1579 }
1580
1581 template<typename LeftType, typename RightType>
opLessThan(RuntimeEnvironment *,const intrusive_ptr<const RightValue> LeftTypeOp,const intrusive_ptr<const RightValue> RightTypeOp,const CharPointer &,const CharPointer &)1582 intrusive_ptr<RightValue> opLessThan(RuntimeEnvironment *, const intrusive_ptr<const RightValue> LeftTypeOp, const intrusive_ptr<const RightValue> RightTypeOp, const CharPointer &, const CharPointer &) {
1583 return Value::from(theValue(intrusive_ptr_cast<const LeftType>(LeftTypeOp)) < theValue(intrusive_ptr_cast<const RightType>(RightTypeOp)));
1584 }
1585
1586 template<typename LeftType, typename RightType>
opLessOrEqual(RuntimeEnvironment *,const intrusive_ptr<const RightValue> LeftTypeOp,const intrusive_ptr<const RightValue> RightTypeOp,const CharPointer &,const CharPointer &)1587 intrusive_ptr<RightValue> opLessOrEqual(RuntimeEnvironment *, const intrusive_ptr<const RightValue> LeftTypeOp, const intrusive_ptr<const RightValue> RightTypeOp, const CharPointer &, const CharPointer &) {
1588 return Value::from(theValue(intrusive_ptr_cast<const LeftType>(LeftTypeOp)) <= theValue(intrusive_ptr_cast<const RightType>(RightTypeOp)));
1589 }
1590
1591 template<typename LeftType, typename RightType>
opGreaterOrEqual(RuntimeEnvironment *,const intrusive_ptr<const RightValue> LeftTypeOp,const intrusive_ptr<const RightValue> RightTypeOp,const CharPointer &,const CharPointer &)1592 intrusive_ptr<RightValue> opGreaterOrEqual(RuntimeEnvironment *, const intrusive_ptr<const RightValue> LeftTypeOp, const intrusive_ptr<const RightValue> RightTypeOp, const CharPointer &, const CharPointer &) {
1593 return Value::from(theValue(intrusive_ptr_cast<const LeftType>(LeftTypeOp)) >= theValue(intrusive_ptr_cast<const RightType>(RightTypeOp)));
1594 }
1595
1596 template<typename LeftType, typename RightType>
opGreaterThan(RuntimeEnvironment *,const intrusive_ptr<const RightValue> LeftTypeOp,const intrusive_ptr<const RightValue> RightTypeOp,const CharPointer &,const CharPointer &)1597 intrusive_ptr<RightValue> opGreaterThan(RuntimeEnvironment *, const intrusive_ptr<const RightValue> LeftTypeOp, const intrusive_ptr<const RightValue> RightTypeOp, const CharPointer &, const CharPointer &) {
1598 return Value::from(theValue(intrusive_ptr_cast<const LeftType>(LeftTypeOp)) > theValue(intrusive_ptr_cast<const RightType>(RightTypeOp)));
1599 }
1600
1601 template<typename LeftType, typename RightType>
opPlus(RuntimeEnvironment *,const intrusive_ptr<const RightValue> LeftTypeOp,const intrusive_ptr<const RightValue> RightTypeOp,const CharPointer &,const CharPointer &)1602 intrusive_ptr<RightValue> opPlus(RuntimeEnvironment *, const intrusive_ptr<const RightValue> LeftTypeOp, const intrusive_ptr<const RightValue> RightTypeOp, const CharPointer &, const CharPointer &) {
1603 return Value::simplifiedValueFrom(theValue(intrusive_ptr_cast<const LeftType>(LeftTypeOp)) + theValue(intrusive_ptr_cast<const RightType>(RightTypeOp)));
1604 }
1605
1606 template<typename LeftType, typename RightType>
opMinus(RuntimeEnvironment *,const intrusive_ptr<const RightValue> LeftTypeOp,const intrusive_ptr<const RightValue> RightTypeOp,const CharPointer &,const CharPointer &)1607 intrusive_ptr<RightValue> opMinus(RuntimeEnvironment *, const intrusive_ptr<const RightValue> LeftTypeOp, const intrusive_ptr<const RightValue> RightTypeOp, const CharPointer &, const CharPointer &) {
1608 return Value::simplifiedValueFrom(theValue(intrusive_ptr_cast<const LeftType>(LeftTypeOp)) - theValue(intrusive_ptr_cast<const RightType>(RightTypeOp)));
1609 }
1610
1611 template<typename LeftType, typename RightType>
opStar(RuntimeEnvironment *,const intrusive_ptr<const RightValue> LeftTypeOp,const intrusive_ptr<const RightValue> RightTypeOp,const CharPointer &,const CharPointer &)1612 intrusive_ptr<RightValue> opStar(RuntimeEnvironment *, const intrusive_ptr<const RightValue> LeftTypeOp, const intrusive_ptr<const RightValue> RightTypeOp, const CharPointer &, const CharPointer &) {
1613 return Value::simplifiedValueFrom(theValue(intrusive_ptr_cast<const LeftType>(LeftTypeOp)) * theValue(intrusive_ptr_cast<const RightType>(RightTypeOp)));
1614 }
1615
1616 template<typename LeftType, typename RightType>
opSlash(RuntimeEnvironment *,const intrusive_ptr<const RightValue> LeftTypeOp,const intrusive_ptr<const RightValue> RightTypeOp,const CharPointer &,const CharPointer &)1617 intrusive_ptr<RightValue> opSlash(RuntimeEnvironment *, const intrusive_ptr<const RightValue> LeftTypeOp, const intrusive_ptr<const RightValue> RightTypeOp, const CharPointer &, const CharPointer &) {
1618 return Value::simplifiedValueFrom(theValue(intrusive_ptr_cast<const LeftType>(LeftTypeOp)) / theValue(intrusive_ptr_cast<const RightType>(RightTypeOp)));
1619 }
1620
1621 //----- operators <, >, <=, >= --------------------------------------------
1622 // not implemented as such in CoCoALib
1623
opLessThan_RINGELEM_RINGELEM(RuntimeEnvironment *,const intrusive_ptr<const RightValue> leftOp,const intrusive_ptr<const RightValue> rightOp,const CharPointer & beginOperatorSourcePosition,const CharPointer & endOperatorSourcePosition)1624 intrusive_ptr<RightValue> opLessThan_RINGELEM_RINGELEM(RuntimeEnvironment *, const intrusive_ptr<const RightValue> leftOp, const intrusive_ptr<const RightValue> rightOp, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1625 intrusive_ptr<const RINGELEM> a = intrusive_ptr_cast<const RINGELEM>(leftOp);
1626 intrusive_ptr<const RINGELEM> b = intrusive_ptr_cast<const RINGELEM>(rightOp);
1627 if (IsOrderedDomain(owner(a->theRingElem)))
1628 return Value::from(a->theRingElem < b->theRingElem);
1629 if (IsMonomial(a->theRingElem) && IsMonomial(b->theRingElem)
1630 && IsOne(LC(a->theRingElem)) && IsOne(LC(b->theRingElem)))
1631 return Value::from(LPP(a->theRingElem) < LPP(b->theRingElem));
1632 throw RuntimeException("RINGELEM can be compared only if in ordered domain or if power-products", beginOperatorSourcePosition, endOperatorSourcePosition);
1633 }
1634
1635
opLessOrEqual_RINGELEM_RINGELEM(RuntimeEnvironment *,const intrusive_ptr<const RightValue> leftOp,const intrusive_ptr<const RightValue> rightOp,const CharPointer & beginOperatorSourcePosition,const CharPointer & endOperatorSourcePosition)1636 intrusive_ptr<RightValue> opLessOrEqual_RINGELEM_RINGELEM(RuntimeEnvironment *, const intrusive_ptr<const RightValue> leftOp, const intrusive_ptr<const RightValue> rightOp, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1637 intrusive_ptr<const RINGELEM> a = intrusive_ptr_cast<const RINGELEM>(leftOp);
1638 intrusive_ptr<const RINGELEM> b = intrusive_ptr_cast<const RINGELEM>(rightOp);
1639 if (IsOrderedDomain(owner(a->theRingElem)))
1640 return Value::from(a->theRingElem <= b->theRingElem);
1641 if (IsMonomial(a->theRingElem) && IsMonomial(b->theRingElem)
1642 && IsOne(LC(a->theRingElem)) && IsOne(LC(b->theRingElem)))
1643 return Value::from(LPP(a->theRingElem) <= LPP(b->theRingElem));
1644 throw RuntimeException("RINGELEM can be compared only if in ordered domain or if power-products", beginOperatorSourcePosition, endOperatorSourcePosition);
1645 }
1646
1647
opGreaterThan_RINGELEM_RINGELEM(RuntimeEnvironment * rv,const intrusive_ptr<const RightValue> leftOp,const intrusive_ptr<const RightValue> rightOp,const CharPointer & beginOperatorSourcePosition,const CharPointer & endOperatorSourcePosition)1648 intrusive_ptr<RightValue> opGreaterThan_RINGELEM_RINGELEM(RuntimeEnvironment *rv, const intrusive_ptr<const RightValue> leftOp, const intrusive_ptr<const RightValue> rightOp, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1649 return opLessThan_RINGELEM_RINGELEM(rv, rightOp, leftOp, beginOperatorSourcePosition, endOperatorSourcePosition);
1650 }
1651
1652
opGreaterOrEqual_RINGELEM_RINGELEM(RuntimeEnvironment * rv,const intrusive_ptr<const RightValue> leftOp,const intrusive_ptr<const RightValue> rightOp,const CharPointer & beginOperatorSourcePosition,const CharPointer & endOperatorSourcePosition)1653 intrusive_ptr<RightValue> opGreaterOrEqual_RINGELEM_RINGELEM(RuntimeEnvironment *rv, const intrusive_ptr<const RightValue> leftOp, const intrusive_ptr<const RightValue> rightOp, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1654 return opLessOrEqual_RINGELEM_RINGELEM(rv, rightOp, leftOp, beginOperatorSourcePosition, endOperatorSourcePosition);
1655 }
1656
1657
opLessThan_IDEAL_IDEAL(RuntimeEnvironment *,const intrusive_ptr<const RightValue>,const intrusive_ptr<const RightValue>,const CharPointer & beginOperatorSourcePosition,const CharPointer & endOperatorSourcePosition)1658 intrusive_ptr<RightValue> opLessThan_IDEAL_IDEAL(RuntimeEnvironment *, const intrusive_ptr<const RightValue> /*leftOp*/, const intrusive_ptr<const RightValue> /*rightOp*/, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1659 throw RuntimeException("IDEAL<IDEAL is obsolete: use IsContained(IDEAL,IDEAL) instead", beginOperatorSourcePosition, endOperatorSourcePosition);
1660 }
1661
opLessOrEqual_IDEAL_IDEAL(RuntimeEnvironment *,const intrusive_ptr<const RightValue>,const intrusive_ptr<const RightValue>,const CharPointer & beginOperatorSourcePosition,const CharPointer & endOperatorSourcePosition)1662 intrusive_ptr<RightValue> opLessOrEqual_IDEAL_IDEAL(RuntimeEnvironment *, const intrusive_ptr<const RightValue> /*leftOp*/, const intrusive_ptr<const RightValue> /*rightOp*/, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1663 throw RuntimeException("IDEAL<=IDEAL is obsolete: use IsContained(IDEAL,IDEAL) instead", beginOperatorSourcePosition, endOperatorSourcePosition);
1664 }
1665
opGreaterOrEqual_IDEAL_IDEAL(RuntimeEnvironment *,const intrusive_ptr<const RightValue>,const intrusive_ptr<const RightValue>,const CharPointer & beginOperatorSourcePosition,const CharPointer & endOperatorSourcePosition)1666 intrusive_ptr<RightValue> opGreaterOrEqual_IDEAL_IDEAL(RuntimeEnvironment *, const intrusive_ptr<const RightValue> /*leftOp*/, const intrusive_ptr<const RightValue> /*rightOp*/, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1667 throw RuntimeException("IDEAL>=IDEAL is obsolete: use IsContained(IDEAL,IDEAL) instead", beginOperatorSourcePosition, endOperatorSourcePosition);
1668 }
1669
opGreaterThan_IDEAL_IDEAL(RuntimeEnvironment *,const intrusive_ptr<const RightValue>,const intrusive_ptr<const RightValue>,const CharPointer & beginOperatorSourcePosition,const CharPointer & endOperatorSourcePosition)1670 intrusive_ptr<RightValue> opGreaterThan_IDEAL_IDEAL(RuntimeEnvironment *, const intrusive_ptr<const RightValue> /*leftOp*/, const intrusive_ptr<const RightValue> /*rightOp*/, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1671 throw RuntimeException("IDEAL>IDEAL is obsolete: use IsContained instead(IDEAL,IDEAL)", beginOperatorSourcePosition, endOperatorSourcePosition);
1672 }
1673
opLessThan_MODULE_MODULE(RuntimeEnvironment *,const intrusive_ptr<const RightValue>,const intrusive_ptr<const RightValue>,const CharPointer & beginOperatorSourcePosition,const CharPointer & endOperatorSourcePosition)1674 intrusive_ptr<RightValue> opLessThan_MODULE_MODULE(RuntimeEnvironment *, const intrusive_ptr<const RightValue> /*leftOp*/, const intrusive_ptr<const RightValue> /*rightOp*/, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1675 throw RuntimeException("MODULE<MODULE is obsolete: use IsContained(MODULE,MODULE) instead", beginOperatorSourcePosition, endOperatorSourcePosition);
1676 }
1677
opLessOrEqual_MODULE_MODULE(RuntimeEnvironment *,const intrusive_ptr<const RightValue>,const intrusive_ptr<const RightValue>,const CharPointer & beginOperatorSourcePosition,const CharPointer & endOperatorSourcePosition)1678 intrusive_ptr<RightValue> opLessOrEqual_MODULE_MODULE(RuntimeEnvironment *, const intrusive_ptr<const RightValue> /*leftOp*/, const intrusive_ptr<const RightValue> /*rightOp*/, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1679 throw RuntimeException("MODULE<=MODULE is obsolete: use IsContained(MODULE,MODULE) instead", beginOperatorSourcePosition, endOperatorSourcePosition);
1680 }
1681
opGreaterOrEqual_MODULE_MODULE(RuntimeEnvironment *,const intrusive_ptr<const RightValue>,const intrusive_ptr<const RightValue>,const CharPointer & beginOperatorSourcePosition,const CharPointer & endOperatorSourcePosition)1682 intrusive_ptr<RightValue> opGreaterOrEqual_MODULE_MODULE(RuntimeEnvironment *, const intrusive_ptr<const RightValue> /*leftOp*/, const intrusive_ptr<const RightValue> /*rightOp*/, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1683 throw RuntimeException("MODULE>=MODULE is obsolete: use IsContained(MODULE,MODULE) instead", beginOperatorSourcePosition, endOperatorSourcePosition);
1684 }
1685
opGreaterThan_MODULE_MODULE(RuntimeEnvironment *,const intrusive_ptr<const RightValue>,const intrusive_ptr<const RightValue>,const CharPointer & beginOperatorSourcePosition,const CharPointer & endOperatorSourcePosition)1686 intrusive_ptr<RightValue> opGreaterThan_MODULE_MODULE(RuntimeEnvironment *, const intrusive_ptr<const RightValue> /*leftOp*/, const intrusive_ptr<const RightValue> /*rightOp*/, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1687 throw RuntimeException("MODULE>MODULE is obsolete: use IsContained(MODULE,MODULE) instead", beginOperatorSourcePosition, endOperatorSourcePosition);
1688 }
1689
1690
1691
1692 //----- opPower_ ---------------------------------------------------------
opPower_RINGELEM_INT(RuntimeEnvironment *,const intrusive_ptr<const RightValue> leftOp,const intrusive_ptr<const RightValue> rightOp,const CharPointer &,const CharPointer &)1693 intrusive_ptr<RightValue> opPower_RINGELEM_INT(RuntimeEnvironment *, const intrusive_ptr<const RightValue> leftOp, const intrusive_ptr<const RightValue> rightOp, const CharPointer &, const CharPointer &) {
1694 intrusive_ptr<const INT> exponent = intrusive_ptr_cast<const INT>(rightOp);
1695 return new RINGELEM(power(intrusive_ptr_cast<const RINGELEM>(leftOp)->theRingElem, exponent->theBigInt));
1696 }
1697
opPower_INT_INT(RuntimeEnvironment *,const intrusive_ptr<const RightValue> leftOp,const intrusive_ptr<const RightValue> rightOp,const CharPointer &,const CharPointer &)1698 intrusive_ptr<RightValue> opPower_INT_INT(RuntimeEnvironment *, const intrusive_ptr<const RightValue> leftOp, const intrusive_ptr<const RightValue> rightOp, const CharPointer &, const CharPointer &) {
1699 intrusive_ptr<const INT> exponent = intrusive_ptr_cast<const INT>(rightOp);
1700 if (exponent->theBigInt<0)
1701 return Value::simplifiedValueFrom(power(BigRat(intrusive_ptr_cast<const INT>(leftOp)->theBigInt,1), exponent->theBigInt));
1702 return new INT(power(intrusive_ptr_cast<const INT>(leftOp)->theBigInt, exponent->theBigInt));
1703 }
1704
opPower_RAT_INT(RuntimeEnvironment *,const intrusive_ptr<const RightValue> leftOp,const intrusive_ptr<const RightValue> rightOp,const CharPointer &,const CharPointer &)1705 intrusive_ptr<RightValue> opPower_RAT_INT(RuntimeEnvironment *, const intrusive_ptr<const RightValue> leftOp, const intrusive_ptr<const RightValue> rightOp, const CharPointer &, const CharPointer &) {
1706 return new RAT(power(intrusive_ptr_cast<const RAT>(leftOp)->theBigRat, intrusive_ptr_cast<const INT>(rightOp)->theBigInt));
1707 }
1708
opPower_MAT_INT(RuntimeEnvironment *,const intrusive_ptr<const RightValue> leftOp,const intrusive_ptr<const RightValue> rightOp,const CharPointer &,const CharPointer &)1709 intrusive_ptr<RightValue> opPower_MAT_INT(RuntimeEnvironment *, const intrusive_ptr<const RightValue> leftOp, const intrusive_ptr<const RightValue> rightOp, const CharPointer &, const CharPointer &) {
1710 intrusive_ptr<const INT> exponent = intrusive_ptr_cast<const INT>(rightOp);
1711 return Value::from(power(intrusive_ptr_cast<const MAT>(leftOp)->theMatrix, exponent->theBigInt));
1712 }
1713
opPower_IDEAL_INT(RuntimeEnvironment *,const intrusive_ptr<const RightValue> leftOp,const intrusive_ptr<const RightValue> rightOp,const CharPointer &,const CharPointer &)1714 intrusive_ptr<RightValue> opPower_IDEAL_INT(RuntimeEnvironment *, const intrusive_ptr<const RightValue> leftOp, const intrusive_ptr<const RightValue> rightOp, const CharPointer &, const CharPointer &) {
1715 intrusive_ptr<const INT> exponent = intrusive_ptr_cast<const INT>(rightOp);
1716 return Value::from(power(intrusive_ptr_cast<const IDEAL>(leftOp)->theIdeal, exponent->theBigInt));
1717 }
1718
1719 // intrusive_ptr<RightValue> opPower_RING_INT(RuntimeEnvironment *, const intrusive_ptr<const RightValue> leftOp, const intrusive_ptr<const RightValue> rightOp, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1720 // intrusive_ptr<const INT> exponent = intrusive_ptr_cast<const INT>(rightOp);
1721 // long n;
1722 // if (!IsConvertible(n, exponent->theBigInt) || n<0)
1723 // throw RuntimeException("Function values cannot be compared", beginOperatorSourcePosition, endOperatorSourcePosition);
1724 // return Value::from(NewFreeModule(intrusive_ptr_cast<const RING>(leftOp)->theRing, n));
1725 // }
1726
1727 //----- opSlash_ ---------------------------------------------------------
1728
opSlash_INT_INT(RuntimeEnvironment *,const intrusive_ptr<const RightValue> leftOp,const intrusive_ptr<const RightValue> rightOp,const CharPointer &,const CharPointer &)1729 intrusive_ptr<RightValue> opSlash_INT_INT(RuntimeEnvironment *, const intrusive_ptr<const RightValue> leftOp, const intrusive_ptr<const RightValue> rightOp, const CharPointer &, const CharPointer &) {
1730 return Value::simplifiedValueFrom(BigRat(intrusive_ptr_cast<const INT>(leftOp)->theBigInt, intrusive_ptr_cast<const INT>(rightOp)->theBigInt));
1731 }
1732
opSlash_RING_IDEAL(RuntimeEnvironment *,const intrusive_ptr<const RightValue> leftOp,const intrusive_ptr<const RightValue> rightOp,const CharPointer &,const CharPointer &)1733 intrusive_ptr<RightValue> opSlash_RING_IDEAL(RuntimeEnvironment *, const intrusive_ptr<const RightValue> leftOp, const intrusive_ptr<const RightValue> rightOp, const CharPointer &, const CharPointer &) {
1734 return Value::from(NewQuotientRing(intrusive_ptr_cast<const RING>(leftOp)->theRing, intrusive_ptr_cast<const IDEAL>(rightOp)->theIdeal));
1735 }
1736
opEqual_Function_Function(RuntimeEnvironment *,const intrusive_ptr<const RightValue>,const intrusive_ptr<const RightValue>,const CharPointer & beginOperatorSourcePosition,const CharPointer & endOperatorSourcePosition)1737 intrusive_ptr<RightValue> opEqual_Function_Function(RuntimeEnvironment *, const intrusive_ptr<const RightValue>, const intrusive_ptr<const RightValue>, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1738 throw RuntimeException("Function values cannot be compared", beginOperatorSourcePosition, endOperatorSourcePosition);
1739 }
1740
opNotEqual_Function_Function(RuntimeEnvironment * runtimeEnv,const intrusive_ptr<const RightValue> leftOp,const intrusive_ptr<const RightValue> rightOp,const CharPointer & beginOperatorSourcePosition,const CharPointer & endOperatorSourcePosition)1741 intrusive_ptr<RightValue> opNotEqual_Function_Function(RuntimeEnvironment *runtimeEnv, const intrusive_ptr<const RightValue> leftOp, const intrusive_ptr<const RightValue> rightOp, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1742 return Value::from(!intrusive_ptr_cast<BOOL>(opEqual_Function_Function(runtimeEnv, leftOp, rightOp, beginOperatorSourcePosition, endOperatorSourcePosition))->theBool);
1743 }
1744
opEqual_LIST_LIST(RuntimeEnvironment * runtimeEnv,const intrusive_ptr<const RightValue> leftOp,const intrusive_ptr<const RightValue> rightOp,const CharPointer & beginOperatorSourcePosition,const CharPointer & endOperatorSourcePosition)1745 intrusive_ptr<RightValue> opEqual_LIST_LIST(RuntimeEnvironment *runtimeEnv, const intrusive_ptr<const RightValue> leftOp, const intrusive_ptr<const RightValue> rightOp, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1746 intrusive_ptr<const LIST> l1 = intrusive_ptr_cast<const LIST>(leftOp);
1747 intrusive_ptr<const LIST> l2 = intrusive_ptr_cast<const LIST>(rightOp);
1748 const LIST::ContainerType::size_type size = l1->size();
1749 if (size!=l2->size())
1750 return BOOL::falseValue;
1751 for(LIST::ContainerType::size_type a=0; a<size; ++a) {
1752 intrusive_ptr<BOOL> b = intrusive_ptr_cast<BOOL>(runtimeEnv->binaryOperatorDispatch(l1->getValue(a), l2->getValue(a), RuntimeEnvironment::opEqualMap, beginOperatorSourcePosition, endOperatorSourcePosition));
1753 if (!b->theBool)
1754 return b;
1755 }
1756 return BOOL::trueValue;
1757 }
1758
opPlus_LIST_LIST(RuntimeEnvironment * runtimeEnv,const intrusive_ptr<const RightValue> leftOp,const intrusive_ptr<const RightValue> rightOp,const CharPointer & beginOperatorSourcePosition,const CharPointer & endOperatorSourcePosition)1759 intrusive_ptr<RightValue> opPlus_LIST_LIST(RuntimeEnvironment *runtimeEnv, const intrusive_ptr<const RightValue> leftOp, const intrusive_ptr<const RightValue> rightOp, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1760 intrusive_ptr<const LIST> l1 = intrusive_ptr_cast<const LIST>(leftOp);
1761 intrusive_ptr<const LIST> l2 = intrusive_ptr_cast<const LIST>(rightOp);
1762 intrusive_ptr<LIST> result = new LIST();
1763 const LIST::ContainerType::size_type size = l1->size();
1764 if (size!=l2->size())
1765 throw RuntimeException("Cannot sum lists of different sizes", beginOperatorSourcePosition, endOperatorSourcePosition);
1766 for(LIST::ContainerType::size_type a=0; a<size; ++a)
1767 result->addValue(runtimeEnv->binaryOperatorDispatch(
1768 l1->getValue(a),
1769 l2->getValue(a),
1770 RuntimeEnvironment::opPlusMap,
1771 beginOperatorSourcePosition,
1772 endOperatorSourcePosition));
1773 return result;
1774 }
1775
opMinus_LIST_LIST(RuntimeEnvironment * runtimeEnv,const intrusive_ptr<const RightValue> leftOp,const intrusive_ptr<const RightValue> rightOp,const CharPointer & beginOperatorSourcePosition,const CharPointer & endOperatorSourcePosition)1776 intrusive_ptr<RightValue> opMinus_LIST_LIST(RuntimeEnvironment *runtimeEnv, const intrusive_ptr<const RightValue> leftOp, const intrusive_ptr<const RightValue> rightOp, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1777 intrusive_ptr<const LIST> l1 = intrusive_ptr_cast<const LIST>(leftOp);
1778 intrusive_ptr<const LIST> l2 = intrusive_ptr_cast<const LIST>(rightOp);
1779 intrusive_ptr<LIST> result = new LIST();
1780 const LIST::ContainerType::size_type size = l1->size();
1781 if (size!=l2->size())
1782 throw RuntimeException("Cannot subtract lists of different sizes", beginOperatorSourcePosition, endOperatorSourcePosition);
1783 for(LIST::ContainerType::size_type a=0; a<size; ++a)
1784 result->addValue(runtimeEnv->binaryOperatorDispatch(
1785 l1->getValue(a),
1786 l2->getValue(a),
1787 RuntimeEnvironment::opMinusMap,
1788 beginOperatorSourcePosition,
1789 endOperatorSourcePosition));
1790 return result;
1791 }
1792
opNotEqual_LIST_LIST(RuntimeEnvironment * runtimeEnv,const intrusive_ptr<const RightValue> leftOp,const intrusive_ptr<const RightValue> rightOp,const CharPointer & beginOperatorSourcePosition,const CharPointer & endOperatorSourcePosition)1793 intrusive_ptr<RightValue> opNotEqual_LIST_LIST(RuntimeEnvironment *runtimeEnv, const intrusive_ptr<const RightValue> leftOp, const intrusive_ptr<const RightValue> rightOp, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1794 return Value::from(!intrusive_ptr_cast<BOOL>(opEqual_LIST_LIST(runtimeEnv, leftOp, rightOp, beginOperatorSourcePosition, endOperatorSourcePosition))->theBool);
1795 }
1796
opEqual_RECORD_RECORD(RuntimeEnvironment * runtimeEnv,const intrusive_ptr<const RightValue> leftOp,const intrusive_ptr<const RightValue> rightOp,const CharPointer & beginOperatorSourcePosition,const CharPointer & endOperatorSourcePosition)1797 intrusive_ptr<RightValue> opEqual_RECORD_RECORD(RuntimeEnvironment *runtimeEnv, const intrusive_ptr<const RightValue> leftOp, const intrusive_ptr<const RightValue> rightOp, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1798 intrusive_ptr<const RECORD> r1 = intrusive_ptr_cast<const RECORD>(leftOp);
1799 intrusive_ptr<const RECORD> r2 = intrusive_ptr_cast<const RECORD>(rightOp);
1800 const RECORD::MapType::size_type numberOfFields = r1->numberOfFields();
1801 if (numberOfFields!=r2->numberOfFields())
1802 return BOOL::falseValue;
1803 RECORD::MapType::const_iterator end = r1->end();
1804 int a=0;
1805 for(RECORD::MapType::const_iterator begin = r1->begin(); begin!=end; ++begin, ++a) {
1806 intrusive_ptr<const RightValue> v2 = r2->getFieldNoCheck((*begin).first);
1807 if (!v2)
1808 return BOOL::falseValue;
1809 intrusive_ptr<BOOL> b = intrusive_ptr_cast<BOOL>(runtimeEnv->binaryOperatorDispatch((*begin).second, v2, RuntimeEnvironment::opEqualMap, beginOperatorSourcePosition, endOperatorSourcePosition));
1810 if (!b->theBool)
1811 return b;
1812 }
1813 return BOOL::trueValue;
1814 }
1815
opNotEqual_RECORD_RECORD(RuntimeEnvironment * runtimeEnv,const intrusive_ptr<const RightValue> leftOp,const intrusive_ptr<const RightValue> rightOp,const CharPointer & beginOperatorSourcePosition,const CharPointer & endOperatorSourcePosition)1816 intrusive_ptr<RightValue> opNotEqual_RECORD_RECORD(RuntimeEnvironment *runtimeEnv, const intrusive_ptr<const RightValue> leftOp, const intrusive_ptr<const RightValue> rightOp, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1817 return Value::from(!intrusive_ptr_cast<BOOL>(opEqual_RECORD_RECORD(runtimeEnv, leftOp, rightOp, beginOperatorSourcePosition, endOperatorSourcePosition))->theBool);
1818 }
1819
opStar_IntRatRE_LIST(RuntimeEnvironment * runtimeEnv,const intrusive_ptr<const RightValue> leftOp,const intrusive_ptr<const RightValue> rightOp,const CharPointer & beginOperatorSourcePosition,const CharPointer & endOperatorSourcePosition)1820 intrusive_ptr<RightValue> opStar_IntRatRE_LIST(RuntimeEnvironment *runtimeEnv, const intrusive_ptr<const RightValue> leftOp, const intrusive_ptr<const RightValue> rightOp, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1821 intrusive_ptr<const LIST> list = intrusive_ptr_cast<const LIST>(rightOp);
1822 intrusive_ptr<LIST> result = new LIST();
1823 const LIST::ContainerType::size_type size = list->size();
1824 for(LIST::ContainerType::size_type a=0; a<size; ++a)
1825 result->addValue(runtimeEnv->binaryOperatorDispatch(
1826 leftOp,
1827 list->getValue(a),
1828 RuntimeEnvironment::opStarMap,
1829 beginOperatorSourcePosition,
1830 endOperatorSourcePosition));
1831 return result;
1832 }
1833
opStar_LIST_IntRatRE(RuntimeEnvironment * runtimeEnv,const intrusive_ptr<const RightValue> leftOp,const intrusive_ptr<const RightValue> rightOp,const CharPointer & beginOperatorSourcePosition,const CharPointer & endOperatorSourcePosition)1834 intrusive_ptr<RightValue> opStar_LIST_IntRatRE(RuntimeEnvironment *runtimeEnv, const intrusive_ptr<const RightValue> leftOp, const intrusive_ptr<const RightValue> rightOp, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1835 intrusive_ptr<const LIST> list = intrusive_ptr_cast<const LIST>(leftOp);
1836 intrusive_ptr<LIST> result = new LIST();
1837 const LIST::ContainerType::size_type size = list->size();
1838 for(LIST::ContainerType::size_type a=0; a<size; ++a)
1839 result->addValue(runtimeEnv->binaryOperatorDispatch(
1840 list->getValue(a),
1841 rightOp,
1842 RuntimeEnvironment::opStarMap,
1843 beginOperatorSourcePosition,
1844 endOperatorSourcePosition));
1845 return result;
1846 }
1847
opSlash_LIST_IntRatRE(RuntimeEnvironment * runtimeEnv,const intrusive_ptr<const RightValue> leftOp,const intrusive_ptr<const RightValue> rightOp,const CharPointer & beginOperatorSourcePosition,const CharPointer & endOperatorSourcePosition)1848 intrusive_ptr<RightValue> opSlash_LIST_IntRatRE(RuntimeEnvironment *runtimeEnv, const intrusive_ptr<const RightValue> leftOp, const intrusive_ptr<const RightValue> rightOp, const CharPointer &beginOperatorSourcePosition, const CharPointer &endOperatorSourcePosition) {
1849 intrusive_ptr<const LIST> list = intrusive_ptr_cast<const LIST>(leftOp);
1850 intrusive_ptr<LIST> result = new LIST();
1851 const LIST::ContainerType::size_type size = list->size();
1852 for(LIST::ContainerType::size_type a=0; a<size; ++a)
1853 result->addValue(runtimeEnv->binaryOperatorDispatch(
1854 list->getValue(a),
1855 rightOp,
1856 RuntimeEnvironment::opSlashMap,
1857 beginOperatorSourcePosition,
1858 endOperatorSourcePosition));
1859 return result;
1860 }
1861
1862
opColon_IDEAL_IDEAL(RuntimeEnvironment *,const intrusive_ptr<const RightValue> leftOp,const intrusive_ptr<const RightValue> rightOp,const CharPointer &,const CharPointer &)1863 intrusive_ptr<RightValue> opColon_IDEAL_IDEAL(RuntimeEnvironment * /*runtimeEnv*/, const intrusive_ptr<const RightValue> leftOp, const intrusive_ptr<const RightValue> rightOp, const CharPointer & /*beginOperatorSourcePosition*/, const CharPointer & /*endOperatorSourcePosition*/) {
1864 const intrusive_ptr<const IDEAL> l1 = intrusive_ptr_cast<const IDEAL>(leftOp);
1865 const intrusive_ptr<const IDEAL> l2 = intrusive_ptr_cast<const IDEAL>(rightOp);
1866 return Value::from(colon(l1->theIdeal, l2->theIdeal));
1867 }
1868
1869 RuntimeEnvironment::DispatchMapType RuntimeEnvironment::opPlusMap;
1870 RuntimeEnvironment::DispatchMapType RuntimeEnvironment::opMinusMap;
1871 RuntimeEnvironment::DispatchMapType RuntimeEnvironment::opStarMap;
1872 RuntimeEnvironment::DispatchMapType RuntimeEnvironment::opSlashMap;
1873 RuntimeEnvironment::DispatchMapType RuntimeEnvironment::opLessThanMap;
1874 RuntimeEnvironment::DispatchMapType RuntimeEnvironment::opLessOrEqualMap;
1875 RuntimeEnvironment::DispatchMapType RuntimeEnvironment::opEqualMap;
1876 RuntimeEnvironment::DispatchMapType RuntimeEnvironment::opNotEqualMap;
1877 RuntimeEnvironment::DispatchMapType RuntimeEnvironment::opGreaterOrEqualMap;
1878 RuntimeEnvironment::DispatchMapType RuntimeEnvironment::opGreaterThanMap;
1879 RuntimeEnvironment::DispatchMapType RuntimeEnvironment::opPowerMap;
1880 RuntimeEnvironment::DispatchMapType RuntimeEnvironment::opModMap;
1881 RuntimeEnvironment::DispatchMapType RuntimeEnvironment::opColonMap;
1882
initMaps()1883 void RuntimeEnvironment::initMaps() {
1884 static bool initialized=false;
1885 if (initialized)
1886 return;
1887 initialized = true;
1888
1889 //------ STRING ----------------------------------------
1890 opPlusMap[TYPE::DISPATCH_INDEX_OF_STRING][TYPE::DISPATCH_INDEX_OF_STRING] = opPlus<STRING, STRING>;
1891 opLessThanMap[TYPE::DISPATCH_INDEX_OF_STRING][TYPE::DISPATCH_INDEX_OF_STRING] = opLessThan<STRING, STRING>;
1892 opLessOrEqualMap[TYPE::DISPATCH_INDEX_OF_STRING][TYPE::DISPATCH_INDEX_OF_STRING] = opLessOrEqual<STRING, STRING>;
1893 opEqualMap[TYPE::DISPATCH_INDEX_OF_STRING][TYPE::DISPATCH_INDEX_OF_STRING] = opEqual<STRING, STRING>;
1894 opNotEqualMap[TYPE::DISPATCH_INDEX_OF_STRING][TYPE::DISPATCH_INDEX_OF_STRING] = opNotEqual<STRING, STRING>;
1895 opGreaterOrEqualMap[TYPE::DISPATCH_INDEX_OF_STRING][TYPE::DISPATCH_INDEX_OF_STRING] = opGreaterOrEqual<STRING, STRING>;
1896 opGreaterThanMap[TYPE::DISPATCH_INDEX_OF_STRING][TYPE::DISPATCH_INDEX_OF_STRING] = opGreaterThan<STRING, STRING>;
1897
1898 //------ BIGINT ----------------------------------------
1899 opPlusMap[TYPE::DISPATCH_INDEX_OF_BIGINT][TYPE::DISPATCH_INDEX_OF_BIGINT] = opPlus<INT, INT>;
1900 opMinusMap[TYPE::DISPATCH_INDEX_OF_BIGINT][TYPE::DISPATCH_INDEX_OF_BIGINT] = opMinus<INT, INT>;
1901 opStarMap[TYPE::DISPATCH_INDEX_OF_BIGINT][TYPE::DISPATCH_INDEX_OF_BIGINT] = opStar<INT, INT>;
1902 opSlashMap[TYPE::DISPATCH_INDEX_OF_BIGINT][TYPE::DISPATCH_INDEX_OF_BIGINT] = opSlash_INT_INT;
1903 opLessThanMap[TYPE::DISPATCH_INDEX_OF_BIGINT][TYPE::DISPATCH_INDEX_OF_BIGINT] = opLessThan<INT, INT>;
1904 opLessOrEqualMap[TYPE::DISPATCH_INDEX_OF_BIGINT][TYPE::DISPATCH_INDEX_OF_BIGINT] = opLessOrEqual<INT, INT>;
1905 opEqualMap[TYPE::DISPATCH_INDEX_OF_BIGINT][TYPE::DISPATCH_INDEX_OF_BIGINT] = opEqual<INT, INT>;
1906 opNotEqualMap[TYPE::DISPATCH_INDEX_OF_BIGINT][TYPE::DISPATCH_INDEX_OF_BIGINT] = opNotEqual<INT, INT>;
1907 opGreaterOrEqualMap[TYPE::DISPATCH_INDEX_OF_BIGINT][TYPE::DISPATCH_INDEX_OF_BIGINT] = opGreaterOrEqual<INT, INT>;
1908 opGreaterThanMap[TYPE::DISPATCH_INDEX_OF_BIGINT][TYPE::DISPATCH_INDEX_OF_BIGINT] = opGreaterThan<INT, INT>;
1909 opPowerMap[TYPE::DISPATCH_INDEX_OF_BIGINT][TYPE::DISPATCH_INDEX_OF_BIGINT] = opPower_INT_INT;
1910
1911 //------ BIGRAT ----------------------------------------
1912 opPlusMap[TYPE::DISPATCH_INDEX_OF_BIGRAT][TYPE::DISPATCH_INDEX_OF_BIGRAT] = opPlus<RAT, RAT>;
1913 opMinusMap[TYPE::DISPATCH_INDEX_OF_BIGRAT][TYPE::DISPATCH_INDEX_OF_BIGRAT] = opMinus<RAT, RAT>;
1914 opStarMap[TYPE::DISPATCH_INDEX_OF_BIGRAT][TYPE::DISPATCH_INDEX_OF_BIGRAT] = opStar<RAT, RAT>;
1915 opSlashMap[TYPE::DISPATCH_INDEX_OF_BIGRAT][TYPE::DISPATCH_INDEX_OF_BIGRAT] = opSlash<RAT, RAT>;
1916 opLessThanMap[TYPE::DISPATCH_INDEX_OF_BIGRAT][TYPE::DISPATCH_INDEX_OF_BIGRAT] = opLessThan<RAT, RAT>;
1917 opLessOrEqualMap[TYPE::DISPATCH_INDEX_OF_BIGRAT][TYPE::DISPATCH_INDEX_OF_BIGRAT] = opLessOrEqual<RAT, RAT>;
1918 opEqualMap[TYPE::DISPATCH_INDEX_OF_BIGRAT][TYPE::DISPATCH_INDEX_OF_BIGRAT] = opEqual<RAT, RAT>;
1919 opNotEqualMap[TYPE::DISPATCH_INDEX_OF_BIGRAT][TYPE::DISPATCH_INDEX_OF_BIGRAT] = opNotEqual<RAT, RAT>;
1920 opGreaterOrEqualMap[TYPE::DISPATCH_INDEX_OF_BIGRAT][TYPE::DISPATCH_INDEX_OF_BIGRAT] = opGreaterOrEqual<RAT, RAT>;
1921 opGreaterThanMap[TYPE::DISPATCH_INDEX_OF_BIGRAT][TYPE::DISPATCH_INDEX_OF_BIGRAT] = opGreaterThan<RAT, RAT>;
1922 opPowerMap[TYPE::DISPATCH_INDEX_OF_BIGRAT][TYPE::DISPATCH_INDEX_OF_BIGINT] = opPower_RAT_INT;
1923
1924 opEqualMap[TYPE::DISPATCH_INDEX_OF_FUNCTION][TYPE::DISPATCH_INDEX_OF_FUNCTION] = opEqual_Function_Function;
1925 opNotEqualMap[TYPE::DISPATCH_INDEX_OF_FUNCTION][TYPE::DISPATCH_INDEX_OF_FUNCTION] = opNotEqual_Function_Function;
1926
1927 //------ LIST ----------------------------------------
1928 opEqualMap[TYPE::DISPATCH_INDEX_OF_LIST][TYPE::DISPATCH_INDEX_OF_LIST] = opEqual_LIST_LIST;
1929 opNotEqualMap[TYPE::DISPATCH_INDEX_OF_LIST][TYPE::DISPATCH_INDEX_OF_LIST] = opNotEqual_LIST_LIST;
1930 opStarMap[TYPE::DISPATCH_INDEX_OF_BIGINT][TYPE::DISPATCH_INDEX_OF_LIST] = opStar_IntRatRE_LIST;
1931 opStarMap[TYPE::DISPATCH_INDEX_OF_BIGRAT][TYPE::DISPATCH_INDEX_OF_LIST] = opStar_IntRatRE_LIST;
1932 opStarMap[TYPE::DISPATCH_INDEX_OF_RINGELEM][TYPE::DISPATCH_INDEX_OF_LIST] = opStar_IntRatRE_LIST;
1933 opStarMap[TYPE::DISPATCH_INDEX_OF_LIST][TYPE::DISPATCH_INDEX_OF_BIGINT] = opStar_LIST_IntRatRE;
1934 opStarMap[TYPE::DISPATCH_INDEX_OF_LIST][TYPE::DISPATCH_INDEX_OF_BIGRAT] = opStar_LIST_IntRatRE;
1935 opStarMap[TYPE::DISPATCH_INDEX_OF_LIST][TYPE::DISPATCH_INDEX_OF_RINGELEM] = opStar_LIST_IntRatRE;
1936 opSlashMap[TYPE::DISPATCH_INDEX_OF_LIST][TYPE::DISPATCH_INDEX_OF_BIGINT] = opSlash_LIST_IntRatRE;
1937 opSlashMap[TYPE::DISPATCH_INDEX_OF_LIST][TYPE::DISPATCH_INDEX_OF_BIGRAT] = opSlash_LIST_IntRatRE;
1938 opSlashMap[TYPE::DISPATCH_INDEX_OF_LIST][TYPE::DISPATCH_INDEX_OF_RINGELEM] = opSlash_LIST_IntRatRE;
1939 opPlusMap[TYPE::DISPATCH_INDEX_OF_LIST][TYPE::DISPATCH_INDEX_OF_LIST] = opPlus_LIST_LIST;
1940 opMinusMap[TYPE::DISPATCH_INDEX_OF_LIST][TYPE::DISPATCH_INDEX_OF_LIST] = opMinus_LIST_LIST;
1941
1942 //------ MAT ----------------------------------------
1943 opStarMap[TYPE::DISPATCH_INDEX_OF_MAT][TYPE::DISPATCH_INDEX_OF_MAT] = opStar<MAT, MAT>;
1944 opStarMap[TYPE::DISPATCH_INDEX_OF_BIGINT][TYPE::DISPATCH_INDEX_OF_MAT] = opStar<INT, MAT>;
1945 opStarMap[TYPE::DISPATCH_INDEX_OF_BIGRAT][TYPE::DISPATCH_INDEX_OF_MAT] = opStar<RAT, MAT>;
1946 opStarMap[TYPE::DISPATCH_INDEX_OF_RINGELEM][TYPE::DISPATCH_INDEX_OF_MAT] = opStar<RINGELEM, MAT>;
1947 opStarMap[TYPE::DISPATCH_INDEX_OF_MAT][TYPE::DISPATCH_INDEX_OF_BIGINT] = opStar<MAT, INT>;
1948 opStarMap[TYPE::DISPATCH_INDEX_OF_MAT][TYPE::DISPATCH_INDEX_OF_BIGRAT] = opStar<MAT, RAT>;
1949 opStarMap[TYPE::DISPATCH_INDEX_OF_MAT][TYPE::DISPATCH_INDEX_OF_RINGELEM] = opStar<MAT, RINGELEM>;
1950 opPlusMap[TYPE::DISPATCH_INDEX_OF_MAT][TYPE::DISPATCH_INDEX_OF_MAT] = opPlus<MAT, MAT>;
1951 opMinusMap[TYPE::DISPATCH_INDEX_OF_MAT][TYPE::DISPATCH_INDEX_OF_MAT] = opMinus<MAT, MAT>;
1952 opEqualMap[TYPE::DISPATCH_INDEX_OF_MAT][TYPE::DISPATCH_INDEX_OF_MAT] = opEqual<MAT, MAT>;
1953 opNotEqualMap[TYPE::DISPATCH_INDEX_OF_MAT][TYPE::DISPATCH_INDEX_OF_MAT] = opNotEqual<MAT, MAT>;
1954 opPowerMap[TYPE::DISPATCH_INDEX_OF_MAT][TYPE::DISPATCH_INDEX_OF_BIGINT] = opPower_MAT_INT;
1955 opSlashMap[TYPE::DISPATCH_INDEX_OF_MAT][TYPE::DISPATCH_INDEX_OF_BIGINT] = opSlash<MAT, INT>;
1956 opSlashMap[TYPE::DISPATCH_INDEX_OF_MAT][TYPE::DISPATCH_INDEX_OF_BIGRAT] = opSlash<MAT, RAT>;
1957 opSlashMap[TYPE::DISPATCH_INDEX_OF_MAT][TYPE::DISPATCH_INDEX_OF_RINGELEM] = opSlash<MAT, RINGELEM>;
1958
1959 //------ RECORD ----------------------------------------
1960 opEqualMap[TYPE::DISPATCH_INDEX_OF_RECORD][TYPE::DISPATCH_INDEX_OF_RECORD] = opEqual_RECORD_RECORD;
1961 opNotEqualMap[TYPE::DISPATCH_INDEX_OF_RECORD][TYPE::DISPATCH_INDEX_OF_RECORD] = opNotEqual_RECORD_RECORD;
1962
1963 //------ BOOL ----------------------------------------
1964 opEqualMap[TYPE::DISPATCH_INDEX_OF_BOOL][TYPE::DISPATCH_INDEX_OF_BOOL] = opEqual<BOOL, BOOL>;
1965 opNotEqualMap[TYPE::DISPATCH_INDEX_OF_BOOL][TYPE::DISPATCH_INDEX_OF_BOOL] = opNotEqual<BOOL, BOOL>;
1966
1967 //------ TYPE ----------------------------------------
1968 opEqualMap[TYPE::DISPATCH_INDEX_OF_TYPE][TYPE::DISPATCH_INDEX_OF_TYPE] = opEqual<TYPE, TYPE>;
1969 opNotEqualMap[TYPE::DISPATCH_INDEX_OF_TYPE][TYPE::DISPATCH_INDEX_OF_TYPE] = opNotEqual<TYPE, TYPE>;
1970
1971 //------ RINGELEM ----------------------------------------
1972 opPlusMap[TYPE::DISPATCH_INDEX_OF_RINGELEM][TYPE::DISPATCH_INDEX_OF_RINGELEM] = opPlus<RINGELEM, RINGELEM>;
1973 opMinusMap[TYPE::DISPATCH_INDEX_OF_RINGELEM][TYPE::DISPATCH_INDEX_OF_RINGELEM] = opMinus<RINGELEM, RINGELEM>;
1974 opStarMap[TYPE::DISPATCH_INDEX_OF_RINGELEM][TYPE::DISPATCH_INDEX_OF_RINGELEM] = opStar<RINGELEM, RINGELEM>;
1975 opSlashMap[TYPE::DISPATCH_INDEX_OF_RINGELEM][TYPE::DISPATCH_INDEX_OF_RINGELEM] = opSlash<RINGELEM, RINGELEM>;
1976 // opLessThanMap[TYPE::DISPATCH_INDEX_OF_RINGELEM][TYPE::DISPATCH_INDEX_OF_RINGELEM] = opLessThan<RINGELEM, RINGELEM>;
1977 // opLessOrEqualMap[TYPE::DISPATCH_INDEX_OF_RINGELEM][TYPE::DISPATCH_INDEX_OF_RINGELEM] = opLessOrEqual<RINGELEM, RINGELEM>;
1978 opLessThanMap[TYPE::DISPATCH_INDEX_OF_RINGELEM][TYPE::DISPATCH_INDEX_OF_RINGELEM] = opLessThan_RINGELEM_RINGELEM;
1979 opLessOrEqualMap[TYPE::DISPATCH_INDEX_OF_RINGELEM][TYPE::DISPATCH_INDEX_OF_RINGELEM] = opLessOrEqual_RINGELEM_RINGELEM;
1980 opEqualMap[TYPE::DISPATCH_INDEX_OF_RINGELEM][TYPE::DISPATCH_INDEX_OF_RINGELEM] = opEqual<RINGELEM, RINGELEM>;
1981 opNotEqualMap[TYPE::DISPATCH_INDEX_OF_RINGELEM][TYPE::DISPATCH_INDEX_OF_RINGELEM] = opNotEqual<RINGELEM, RINGELEM>;
1982 // opGreaterOrEqualMap[TYPE::DISPATCH_INDEX_OF_RINGELEM][TYPE::DISPATCH_INDEX_OF_RINGELEM] = opGreaterOrEqual<RINGELEM, RINGELEM>;
1983 // opGreaterThanMap[TYPE::DISPATCH_INDEX_OF_RINGELEM][TYPE::DISPATCH_INDEX_OF_RINGELEM] = opGreaterThan<RINGELEM, RINGELEM>;
1984 opGreaterOrEqualMap[TYPE::DISPATCH_INDEX_OF_RINGELEM][TYPE::DISPATCH_INDEX_OF_RINGELEM] = opGreaterOrEqual_RINGELEM_RINGELEM;
1985 opGreaterThanMap[TYPE::DISPATCH_INDEX_OF_RINGELEM][TYPE::DISPATCH_INDEX_OF_RINGELEM] = opGreaterThan_RINGELEM_RINGELEM;
1986 opPowerMap[TYPE::DISPATCH_INDEX_OF_RINGELEM][TYPE::DISPATCH_INDEX_OF_BIGINT] = opPower_RINGELEM_INT;
1987
1988 //------ MODULEELEM ----------------------------------------
1989 opStarMap[TYPE::DISPATCH_INDEX_OF_BIGINT][TYPE::DISPATCH_INDEX_OF_MODULEELEM] = opStar<INT, MODULEELEM>;
1990 opStarMap[TYPE::DISPATCH_INDEX_OF_BIGRAT][TYPE::DISPATCH_INDEX_OF_MODULEELEM] = opStar<RAT, MODULEELEM>;
1991 opStarMap[TYPE::DISPATCH_INDEX_OF_RINGELEM][TYPE::DISPATCH_INDEX_OF_MODULEELEM] = opStar<RINGELEM, MODULEELEM>;
1992 opStarMap[TYPE::DISPATCH_INDEX_OF_MODULEELEM][TYPE::DISPATCH_INDEX_OF_BIGINT] = opStar<MODULEELEM, INT>;
1993 opStarMap[TYPE::DISPATCH_INDEX_OF_MODULEELEM][TYPE::DISPATCH_INDEX_OF_BIGRAT] = opStar<MODULEELEM, RAT>;
1994 opStarMap[TYPE::DISPATCH_INDEX_OF_MODULEELEM][TYPE::DISPATCH_INDEX_OF_RINGELEM] = opStar<MODULEELEM, RINGELEM>;
1995 opPlusMap[TYPE::DISPATCH_INDEX_OF_MODULEELEM][TYPE::DISPATCH_INDEX_OF_MODULEELEM] = opPlus<MODULEELEM, MODULEELEM>;
1996 opMinusMap[TYPE::DISPATCH_INDEX_OF_MODULEELEM][TYPE::DISPATCH_INDEX_OF_MODULEELEM] = opMinus<MODULEELEM, MODULEELEM>;
1997 opEqualMap[TYPE::DISPATCH_INDEX_OF_MODULEELEM][TYPE::DISPATCH_INDEX_OF_MODULEELEM] = opEqual<MODULEELEM, MODULEELEM>;
1998 opNotEqualMap[TYPE::DISPATCH_INDEX_OF_MODULEELEM][TYPE::DISPATCH_INDEX_OF_MODULEELEM] = opNotEqual<MODULEELEM, MODULEELEM>;
1999 opSlashMap[TYPE::DISPATCH_INDEX_OF_MODULEELEM][TYPE::DISPATCH_INDEX_OF_BIGINT] = opSlash<MODULEELEM, INT>;
2000 opSlashMap[TYPE::DISPATCH_INDEX_OF_MODULEELEM][TYPE::DISPATCH_INDEX_OF_BIGRAT] = opSlash<MODULEELEM, RAT>;
2001 opSlashMap[TYPE::DISPATCH_INDEX_OF_MODULEELEM][TYPE::DISPATCH_INDEX_OF_RINGELEM] = opSlash<MODULEELEM, RINGELEM>;
2002
2003 //------ RING ----------------------------------------
2004 opEqualMap[TYPE::DISPATCH_INDEX_OF_RING][TYPE::DISPATCH_INDEX_OF_RING] = opEqual<RING, RING>;
2005 opNotEqualMap[TYPE::DISPATCH_INDEX_OF_RING][TYPE::DISPATCH_INDEX_OF_RING] = opNotEqual<RING, RING>;
2006 opSlashMap[TYPE::DISPATCH_INDEX_OF_RING][TYPE::DISPATCH_INDEX_OF_IDEAL] = opSlash_RING_IDEAL;
2007 // opPowerMap[TYPE::DISPATCH_INDEX_OF_RING][TYPE::DISPATCH_INDEX_OF_BIGINT] = opPower_RING_INT;
2008
2009 //------ MODULE ----------------------------------------
2010 opEqualMap[TYPE::DISPATCH_INDEX_OF_MODULE][TYPE::DISPATCH_INDEX_OF_MODULE] = opEqual<MODULE, MODULE>;
2011 opNotEqualMap[TYPE::DISPATCH_INDEX_OF_MODULE][TYPE::DISPATCH_INDEX_OF_MODULE] = opNotEqual<MODULE, MODULE>;
2012 // opSlashMap[TYPE::DISPATCH_INDEX_OF_RING][TYPE::DISPATCH_INDEX_OF_IDEAL] = opSlash_RING_IDEAL;
2013 opGreaterThanMap[TYPE::DISPATCH_INDEX_OF_MODULE][TYPE::DISPATCH_INDEX_OF_MODULE] = opGreaterThan_MODULE_MODULE;
2014 opGreaterOrEqualMap[TYPE::DISPATCH_INDEX_OF_MODULE][TYPE::DISPATCH_INDEX_OF_MODULE] = opGreaterOrEqual_MODULE_MODULE;
2015 opLessThanMap[TYPE::DISPATCH_INDEX_OF_MODULE][TYPE::DISPATCH_INDEX_OF_MODULE] = opLessThan_MODULE_MODULE;
2016 opLessOrEqualMap[TYPE::DISPATCH_INDEX_OF_MODULE][TYPE::DISPATCH_INDEX_OF_MODULE] = opLessOrEqual_MODULE_MODULE;
2017
2018 //------ IDEAL ----------------------------------------
2019 opPlusMap[TYPE::DISPATCH_INDEX_OF_IDEAL][TYPE::DISPATCH_INDEX_OF_IDEAL] = opPlus<IDEAL, IDEAL>;
2020 opStarMap[TYPE::DISPATCH_INDEX_OF_IDEAL][TYPE::DISPATCH_INDEX_OF_RINGELEM] = opStar<IDEAL, RINGELEM>;
2021 opStarMap[TYPE::DISPATCH_INDEX_OF_RINGELEM][TYPE::DISPATCH_INDEX_OF_IDEAL] = opStar<RINGELEM, IDEAL>;
2022 opStarMap[TYPE::DISPATCH_INDEX_OF_IDEAL][TYPE::DISPATCH_INDEX_OF_IDEAL] = opStar<IDEAL, IDEAL>;
2023 opPowerMap[TYPE::DISPATCH_INDEX_OF_IDEAL][TYPE::DISPATCH_INDEX_OF_BIGINT] = opPower_IDEAL_INT;
2024 opEqualMap[TYPE::DISPATCH_INDEX_OF_IDEAL][TYPE::DISPATCH_INDEX_OF_IDEAL] = opEqual<IDEAL, IDEAL>;
2025 opNotEqualMap[TYPE::DISPATCH_INDEX_OF_IDEAL][TYPE::DISPATCH_INDEX_OF_IDEAL] = opNotEqual<IDEAL, IDEAL>;
2026 opColonMap[TYPE::DISPATCH_INDEX_OF_IDEAL][TYPE::DISPATCH_INDEX_OF_IDEAL] = opColon_IDEAL_IDEAL;
2027 opGreaterThanMap[TYPE::DISPATCH_INDEX_OF_IDEAL][TYPE::DISPATCH_INDEX_OF_IDEAL] = opGreaterThan_IDEAL_IDEAL;
2028 opGreaterOrEqualMap[TYPE::DISPATCH_INDEX_OF_IDEAL][TYPE::DISPATCH_INDEX_OF_IDEAL] = opGreaterOrEqual_IDEAL_IDEAL;
2029 opLessThanMap[TYPE::DISPATCH_INDEX_OF_IDEAL][TYPE::DISPATCH_INDEX_OF_IDEAL] = opLessThan_IDEAL_IDEAL;
2030 opLessOrEqualMap[TYPE::DISPATCH_INDEX_OF_IDEAL][TYPE::DISPATCH_INDEX_OF_IDEAL] = opLessOrEqual_IDEAL_IDEAL;
2031 }
2032
dumpAsString(ostream & out)2033 ostream &VariableName::dumpAsString(ostream &out) const {
2034 return out << "<" << this->expId->identifier << " @ " <<
2035 static_cast<void *>(this->framePointer.toCheckedPointer()) << "[" << this->slotIndex << "]>";
2036 }
2037
dumpAsString(std::ostream & out)2038 ostream &FieldAccess::dumpAsString(std::ostream &out) const {
2039 return out << "<access to field " << this->fieldName << " of " << this->targetLV << ">";
2040 }
2041
dumpAsString(std::ostream & out)2042 ostream &IntegerIndexedAccess::dumpAsString(std::ostream &out) const {
2043 return out << "<access to index " << this->index << " of " << this->targetLV << ">";
2044 }
2045
dumpAsString(std::ostream & out)2046 ostream &StringIndexedAccess::dumpAsString(std::ostream &out) const {
2047 return out << "<indexed-access to field " << this->fieldName << " of " << this->targetLV << ">";
2048 }
2049
targetAsRECORD()2050 intrusive_ptr<RECORD> FieldAccess::targetAsRECORD() {
2051 intrusive_ptr<RightValue> target = this->targetLV->asRightValue();
2052 intrusive_ptr<RECORD> rv = dynamic_pointer_cast<RECORD>(target);
2053 if (!rv)
2054 throw WrongTypeException(RECORD::type->name, target->getType()->name, this->fieldAccessExp->targetExp);
2055 return rv;
2056 }
2057
targetAsRECORD()2058 intrusive_ptr<RECORD> StringIndexedAccess::targetAsRECORD() {
2059 intrusive_ptr<RightValue> target = this->targetLV->asRightValue();
2060 intrusive_ptr<RECORD> rv = dynamic_pointer_cast<RECORD>(target);
2061 if (!rv)
2062 throw WrongTypeException(
2063 RECORD::type->name,
2064 target->getType()->name,
2065 this->targetExpBegin,
2066 this->targetExpEnd);
2067 return rv;
2068 }
2069
targetAsListOrMatrixOrMatrixRow(int & which)2070 intrusive_ptr<RightValue> IntegerIndexedAccess::targetAsListOrMatrixOrMatrixRow(int &which) {
2071 const intrusive_ptr<RightValue> target = this->targetLV->asRightValue();
2072 if (dynamic_pointer_cast<LIST>(target)) {
2073 which = 1;
2074 return target;
2075 }
2076 if (dynamic_pointer_cast<MAT>(target)) {
2077 which = 2;
2078 return target;
2079 }
2080 if (dynamic_pointer_cast<MatrixRowValue>(target)) {
2081 which = 3;
2082 return target;
2083 }
2084 throw WrongTypeException(
2085 LIST::type->name + ", " + MAT::type->name + " or " + MatrixRowValue::type->name,
2086 target->getType()->name,
2087 this->targetExpBegin,
2088 this->targetExpEnd);
2089 }
2090
getIndexFromBigInt(const BigInt & N,intrusive_ptr<const LIST> list)2091 LIST::ContainerType::size_type IntegerIndexedAccess::getIndexFromBigInt(const BigInt &N, intrusive_ptr<const LIST> list) const {
2092 long l;
2093 if (!IsConvertible(l, N) || l<=0 || static_cast<LIST::ContainerType::size_type>(l)>list->size())
2094 throw IndexOutOfRangeException(N, list->size(), this->indexExpBegin, this->indexExpEnd);
2095 return l-1;
2096 }
2097
getIndexFromBigInt(const BigInt & N,intrusive_ptr<const STRING> str)2098 string::size_type IntegerIndexedAccess::getIndexFromBigInt(const BigInt &N, intrusive_ptr<const STRING> str) const {
2099 long l;
2100 if (!IsConvertible(l, N) || l<=0 || static_cast<string::size_type>(l)>str->theString.size())
2101 throw IndexOutOfRangeException(N, str->theString.size(), this->indexExpBegin, this->indexExpEnd);
2102 return l-1;
2103 }
2104
getIndexFromBigInt(const BigInt & N,intrusive_ptr<const MatrixRowValue> mrv)2105 size_t IntegerIndexedAccess::getIndexFromBigInt(const BigInt &N, intrusive_ptr<const MatrixRowValue> mrv) const {
2106 long l;
2107 if (!IsConvertible(l, N) || l<=0 || static_cast<size_t>(l)>mrv->matrix->numColumns())
2108 throw IndexOutOfRangeException(N, mrv->matrix->numColumns(), this->indexExpBegin, this->indexExpEnd);
2109 return l-1;
2110 }
2111
asRightValue()2112 intrusive_ptr<RightValue> IntegerIndexedAccess::asRightValue() {
2113 return this->targetLV->asRightValue()->indexedByBigInt(new INT(this->index), this->targetExpBegin, this->targetExpEnd, this->indexExpBegin, this->indexExpEnd)->asRightValue();
2114 }
2115
assign(boost::intrusive_ptr<RightValue> value,const CharPointer & valueExpBegin,const CharPointer & valueExpEnd,RuntimeEnvironment * runtimeEnv)2116 void IntegerIndexedAccess::assign(boost::intrusive_ptr<RightValue> value, const CharPointer &valueExpBegin, const CharPointer &valueExpEnd, RuntimeEnvironment *runtimeEnv) {
2117 int which;
2118 intrusive_ptr<RightValue> rv = this->targetAsListOrMatrixOrMatrixRow(which);
2119 switch (which) {
2120 case 1 /* LIST */ : {
2121 const intrusive_ptr<LIST> list = intrusive_ptr_cast<LIST>(rv);
2122 list->setValue(this->getIndexFromBigInt(index, list), value);
2123 }
2124 break;
2125 case 2 /* MAT */ : {
2126 throw RuntimeException("Matrix rows cannot be assigned", this->targetExpBegin, this->indexExpEnd);
2127 }
2128 break;
2129 case 3 /* MatrixRowValue */ : {
2130 try
2131 {
2132 const intrusive_ptr<MatrixRowValue> mrv = intrusive_ptr_cast<MatrixRowValue>(rv);
2133 if (const intrusive_ptr<RINGELEM> ringElem = dynamic_pointer_cast<RINGELEM>(value))
2134 SetEntry(mrv->matrix->theMatrix, mrv->nRow, this->getIndexFromBigInt(index, mrv), ringElem->theRingElem);
2135 else if (const intrusive_ptr<INT> N = dynamic_pointer_cast<INT>(value))
2136 SetEntry(mrv->matrix->theMatrix, mrv->nRow, this->getIndexFromBigInt(index, mrv), N->theBigInt);
2137 else if (const intrusive_ptr<RAT> qq = dynamic_pointer_cast<RAT>(value))
2138 SetEntry(mrv->matrix->theMatrix, mrv->nRow, this->getIndexFromBigInt(index, mrv), qq->theBigRat);
2139 else
2140 throw RuntimeException(value->getType()->name+" cannot be assigned to matrix cells", valueExpBegin, valueExpEnd);
2141 }
2142 catch (const ErrorInfo& err)
2143 {
2144 runtimeEnv->announceCLE(err);
2145 throw RuntimeException(message_forC5(err), valueExpBegin, valueExpEnd);
2146 }
2147 }
2148 break;
2149 default:
2150 assert(false);
2151 }
2152 }
2153
getBase()2154 intrusive_ptr<VariableName> IndexedAccess::getBase() {
2155 return this->targetLV->getBase();
2156 }
2157
assignmentNeedsOwnership()2158 bool IndexedAccess::assignmentNeedsOwnership() const {
2159 return true; // 2019-04-29 cannot simply change to false (see redmine 1228, comment 18)
2160 }
2161
asRightValue()2162 intrusive_ptr<RightValue> FieldAccess::asRightValue() {
2163 intrusive_ptr<RECORD> rv = this->targetAsRECORD();
2164 intrusive_ptr<RightValue> fieldValue = rv->getField(this->fieldName, this->fieldAccessExp->tokName.getBegin(), this->fieldAccessExp->tokName.getEnd());
2165 if (!fieldValue)
2166 throw FieldNotFoundException(this->fieldName, this->fieldAccessExp->tokName.getBegin(), this->fieldAccessExp->tokName.getEnd(), rv);
2167 return fieldValue;
2168 }
2169
asRightValue()2170 intrusive_ptr<RightValue> StringIndexedAccess::asRightValue() {
2171 intrusive_ptr<RECORD> rv = this->targetAsRECORD();
2172 intrusive_ptr<RightValue> fieldValue = rv->getField(this->fieldName, this->indexExpBegin, this->indexExpEnd);
2173 if (!fieldValue)
2174 throw FieldNotFoundException(this->fieldName, this->indexExpBegin, this->indexExpEnd, rv);
2175 return fieldValue;
2176 }
2177
assign(boost::intrusive_ptr<RightValue> value,const CharPointer & valueExpBegin,const CharPointer & valueExpEnd,RuntimeEnvironment *)2178 void StringIndexedAccess::assign(boost::intrusive_ptr<RightValue> value, const CharPointer & valueExpBegin, const CharPointer & valueExpEnd, RuntimeEnvironment * /*runtimeEnv*/) {
2179 intrusive_ptr<RECORD> rv = this->targetAsRECORD();
2180 rv->setField(this->fieldName, value, valueExpBegin, valueExpEnd);
2181 }
2182
assign(boost::intrusive_ptr<RightValue> value,const CharPointer & valueExpBegin,const CharPointer & valueExpEnd,RuntimeEnvironment *)2183 void FieldAccess::assign(boost::intrusive_ptr<RightValue> value, const CharPointer & valueExpBegin, const CharPointer & valueExpEnd, RuntimeEnvironment * /*runtimeEnv*/) {
2184 intrusive_ptr<RECORD> rv = this->targetAsRECORD();
2185 rv->setField(this->fieldName, value, valueExpBegin, valueExpEnd);
2186 }
2187
getBase()2188 intrusive_ptr<VariableName> FieldAccess::getBase() {
2189 return this->targetLV->getBase();
2190 }
2191
assignmentNeedsOwnership()2192 bool FieldAccess::assignmentNeedsOwnership() const {
2193 return true;
2194 }
2195
dumpAsString(ostream & out)2196 ostream &ReferenceVariable::dumpAsString(ostream &out) const {
2197 return out << "<reference to " << this->framePointer.toCheckedPointer() << "[" << this->slotIndex << "]>";
2198 }
2199
referencedSlot()2200 VariableSlot *ReferenceVariable::referencedSlot() const {
2201 return &(this->framePointer.toNonNullCheckedPointer(this->expId)->varSlots[this->slotIndex]);
2202 }
2203
asRightValue()2204 intrusive_ptr<RightValue> ReferenceVariable::asRightValue() {
2205 #ifdef VERBOSE_RUNTIME_DEBUG
2206 cout << "ReferenceVariable::asRightValue expId=" << this->expId << endl;
2207 #endif // #ifdef VERBOSE_RUNTIME_DEBUG
2208 try {
2209 return this->referencedSlot()->value->asRightValue();
2210 } catch (const InterruptException &) {
2211 throw;
2212 } catch (const RuntimeException &) {
2213 this->throwIncompatibleChanges();
2214 return VoidValue::theInstance; // useless, but it keeps the compiler happy ;-)
2215 }
2216 }
2217
throwIncompatibleChanges()2218 void ReferenceVariable::throwIncompatibleChanges() const {
2219 throw RuntimeException(
2220 "Reference variable \""+this->expId->identifier+"\" references an undefined variable or its underlying structure has changed in an incompatible way",
2221 this->expId);
2222 }
2223
assign(intrusive_ptr<RightValue> value,const CharPointer & valueExpBegin,const CharPointer & valueExpEnd,RuntimeEnvironment * runtimeEnv)2224 void ReferenceVariable::assign(intrusive_ptr<RightValue> value, const CharPointer &valueExpBegin, const CharPointer &valueExpEnd, RuntimeEnvironment *runtimeEnv) {
2225 try {
2226 VariableSlot *vs = this->referencedSlot();
2227 checkProtection(vs, this->expId);
2228 return intrusive_ptr_cast<LeftValue>(vs->value)->assign(value, valueExpBegin, valueExpEnd, runtimeEnv);
2229 } catch (const ProtectedVariableException &pe) {
2230 throw ProtectedVariableException(pe.protectedVarName,
2231 "Reference variable "+this->expId->identifier+" cannot be assigned because "+pe.protectedVarName +
2232 ", its (directly or indirectly) referenced variable, is protected",
2233 this->expId);
2234 } catch (const InterruptException &) {
2235 throw;
2236 } catch (const RuntimeException &) {
2237 this->throwIncompatibleChanges();
2238 }
2239 }
2240
getBase()2241 intrusive_ptr<VariableName> ReferenceVariable::getBase() {
2242 return this->referencedLV()->getBase();
2243 }
2244
getBase()2245 intrusive_ptr<VariableName> VariableName::getBase() {
2246 return this;
2247 }
2248
asRightValue()2249 intrusive_ptr<RightValue> VariableName::asRightValue() {
2250 Frame * const f = this->framePointer.toNonNullCheckedPointer(this->expId);
2251 if (this->slotIndex<0) {
2252 assert(f==this->runtimeEnvironment->getTopLevelFrame());
2253 this->slotIndex = this->runtimeEnvironment->slotFor(this->expId->identifier);
2254 if (this->slotIndex<0)
2255 throw VariableNotFoundException(this->expId, this->runtimeEnvironment);
2256 }
2257 #ifdef VERBOSE_RUNTIME_DEBUG
2258 cout << "VariableName::asRightValue for " << this->expId->identifier << ", this->slotIndex=" << this->slotIndex
2259 << ", f->varSlots.size()=" << f->varSlots.size() << endl;
2260 #endif // #ifdef VERBOSE_RUNTIME_DEBUG
2261 assert(static_cast<vector<VariableSlot>::size_type>(this->slotIndex)<f->varSlots.size());
2262 VariableSlot &vs = f->varSlots[this->slotIndex];
2263 if (!vs.value) { // this can only happen when a package has been reloaded (and some of the previous version members are not defined anymore) or an indeterminate has been removed (by Use-ing another ring)
2264 assert(f == this->runtimeEnvironment->getTopLevelFrame());
2265 throw VariableNotFoundException(this->expId, this->runtimeEnvironment);
2266 }
2267 #ifdef VERBOSE_RUNTIME_DEBUG
2268 cout << "f->varSlots[this->slotIndex].value=" << f->varSlots[this->slotIndex].value
2269 << ", f->varSlots[this->slotIndex].value->asRightValue()=" << f->varSlots[this->slotIndex].value->asRightValue() << endl;
2270 #endif // #ifdef VERBOSE_RUNTIME_DEBUG
2271 return f->varSlots[this->slotIndex].value->asRightValue();
2272 }
2273
assignmentNeedsOwnership()2274 bool VariableName::assignmentNeedsOwnership() const {
2275 return false;
2276 }
2277
assignmentNeedsOwnership()2278 bool ReferenceVariable::assignmentNeedsOwnership() const {
2279 return this->referencedLV()->assignmentNeedsOwnership();
2280 }
2281
assign(boost::intrusive_ptr<RightValue> value,const CharPointer &,const CharPointer &,RuntimeEnvironment *)2282 void VariableName::assign(boost::intrusive_ptr<RightValue> value, const CharPointer & /*valueExpBegin*/, const CharPointer & /*valueExpEnd*/, RuntimeEnvironment * /*runtimeEnv*/) {
2283 Frame *f = this->framePointer.toNonNullCheckedPointer(this->expId);
2284 if (this->slotIndex<0) {
2285 assert(f==this->runtimeEnvironment->getTopLevelFrame());
2286 this->slotIndex = this->runtimeEnvironment->slotFor(this->expId->identifier);
2287 if (this->slotIndex<0) {
2288 this->slotIndex = this->runtimeEnvironment->setTopLevelVar(this->expId->identifier, value);
2289 return;
2290 }
2291 }
2292 VariableSlot *vs = &(f->varSlots[this->slotIndex]);
2293 checkProtection(vs, this->expId);
2294 vs->value = value;
2295 }
2296
2297 ostream &operator<<(ostream &out, const Value * const value) {
2298 return value->dumpAsString(out);
2299 }
2300
dumpAsString(std::ostream & out)2301 ostream &INT::dumpAsString(std::ostream &out) const {
2302 return out << this->theBigInt;
2303 }
2304
unaryMinus(const CharPointer &,RuntimeEnvironment * const)2305 intrusive_ptr<RightValue> INT::unaryMinus(const CharPointer &, RuntimeEnvironment * const) {
2306 return intrusive_ptr<INT>(new INT(-this->theBigInt));
2307 }
2308
unaryMinus(const CharPointer &,RuntimeEnvironment * const)2309 intrusive_ptr<RightValue> RAT::unaryMinus(const CharPointer &, RuntimeEnvironment * const) {
2310 return intrusive_ptr<RAT>(new RAT(-this->theBigRat));
2311 }
2312
unaryMinus(const CharPointer &,RuntimeEnvironment * const)2313 intrusive_ptr<RightValue> RINGELEM::unaryMinus(const CharPointer &, RuntimeEnvironment * const) {
2314 return intrusive_ptr<RINGELEM>(new RINGELEM(-this->theRingElem));
2315 }
2316
unaryMinus(const CharPointer &,RuntimeEnvironment * const)2317 intrusive_ptr<RightValue> MAT::unaryMinus(const CharPointer &, RuntimeEnvironment * const) {
2318 return intrusive_ptr<MAT>(new MAT(-this->theMatrix));
2319 }
2320
2321 // ??? JAA cannot figure this one out currently :-( ???
2322 // intrusive_ptr<RightValue> LIST::unaryMinus(const CharPointer &, RuntimeEnvironment * const) {
2323 // intrusive_ptr<const LIST> l1 = this->theList;
2324 // intrusive_ptr<LIST> result = new LIST();
2325 // typedef LIST::ContainerType::size_type INDEX;
2326 // const INDEX size = l1->size();
2327 // for(INDEX i=0; i<size; ++i)
2328 // result->addValue(runtimeEnv->binaryOperatorDispatch(
2329 // l1->getValue(i),
2330 // RuntimeEnvironment::opMinusMap,
2331 // beginOperatorSourcePosition,
2332 // endOperatorSourcePosition));
2333 // return result;
2334 // }
2335
unaryMinus(const CharPointer & op,RuntimeEnvironment * const)2336 intrusive_ptr<RightValue> RightValue::unaryMinus(const CharPointer &op, RuntimeEnvironment * const) {
2337 throw RuntimeException("I don't know how to \"negate\" a "+this->getType()->name, op, op);
2338 }
2339
dumpAsString(std::ostream & out)2340 ostream &RAT::dumpAsString(std::ostream &out) const {
2341 return out << this->theBigRat;
2342 }
2343
dumpAsString(std::ostream & out)2344 ostream &RECORD::dumpAsString(std::ostream &out) const {
2345 out << "record[";
2346 bool first=true;
2347 for(MapType::const_iterator pos = this->fields.begin(); pos!=this->fields.end(); ++pos) {
2348 if (first)
2349 first = false;
2350 else
2351 out << ", ";
2352 out << pos->first << " := " << pos->second;
2353 pos->second->dumpRefCountAsString(out);
2354 }
2355 return out << "]";
2356 }
2357
numberOfFields()2358 RECORD::MapType::size_type RECORD::numberOfFields() const {
2359 return this->fields.size();
2360 }
2361
begin()2362 RECORD::MapType::const_iterator RECORD::begin() const {
2363 return this->fields.begin();
2364 }
2365
end()2366 RECORD::MapType::const_iterator RECORD::end() const {
2367 return this->fields.end();
2368 }
2369
dumpAsString(std::ostream & out)2370 ostream &BOOL::dumpAsString(std::ostream &out) const {
2371 return out << (this->theBool ? "true":"false");
2372 }
2373
dumpAsString(std::ostream & out)2374 ostream &STRING::dumpAsString(std::ostream &out) const {
2375 out << '\"';
2376 BOOST_FOREACH(char c, this->theString) {
2377 switch (c) {
2378 case '\n':
2379 out << "\\n";
2380 break;
2381 case '\r':
2382 out << "\\r";
2383 break;
2384 case '\t':
2385 out << "\\t";
2386 break;
2387 case '\a':
2388 out << "\\a";
2389 break;
2390 case '\'':
2391 out << "\\\'";
2392 break;
2393 case '\"':
2394 out << "\\\"";
2395 break;
2396 case '\\':
2397 out << "\\\\";
2398 break;
2399 default:
2400 out << c;
2401 }
2402 }
2403 return out << '\"';
2404 }
2405
dumpAsString(std::ostream & out)2406 ostream &VoidValue::dumpAsString(std::ostream &out) const {
2407 return out << "<void>";
2408 }
2409
2410 intrusive_ptr<VoidValue> VoidValue::theInstance(new VoidValue());
2411
clone()2412 intrusive_ptr<RightValue> RECORD::clone() {
2413 intrusive_ptr<RECORD> copy(new RECORD);
2414 for(MapType::const_iterator pos = this->fields.begin(); pos!=this->fields.end(); ++pos)
2415 copy->fields.insert(make_pair(pos->first, pos->second->clone()));
2416 return copy;
2417 }
2418
clone()2419 intrusive_ptr<RightValue> LIST::clone() {
2420 intrusive_ptr<LIST> copy(new LIST(this->size()));
2421 BOOST_FOREACH(intrusive_ptr<RightValue> v, this->container) {
2422 copy->addValue(v->clone());
2423 }
2424 return copy;
2425 }
2426
clone()2427 intrusive_ptr<RightValue> MAT::clone() {
2428 const matrix &m = this->theMatrix;
2429 const size_t nRows = NumRows(m);
2430 const size_t nCols = NumCols(m);
2431 matrix clone = matrix(m->myZeroClone(RingOf(m), nRows, nCols));
2432 for(size_t a=0; a<nRows; ++a)
2433 for(size_t b=0; b<nCols; ++b)
2434 SetEntry(clone, a, b, m(a, b));
2435 return new MAT(clone);
2436 }
2437
needsToBeCopiedBeforeChanges()2438 bool LIST::needsToBeCopiedBeforeChanges() const {
2439 if (this->getRefCount()>1)
2440 return true;
2441 for(ContainerType::const_iterator i = this->container.begin(); i!=this->container.end(); ++i)
2442 if ((*i)->needsToBeCopiedBeforeChanges())
2443 return true;
2444 return false;
2445 }
2446
needsToBeCopiedBeforeChanges()2447 bool MAT::needsToBeCopiedBeforeChanges() const {
2448 return this->getRefCount()>1;
2449 }
2450
getValue(ContainerType::size_type index)2451 intrusive_ptr<RightValue> LIST::getValue(ContainerType::size_type index) const {
2452 assert(index<=this->container.size());
2453 return this->container[index];
2454 }
2455
setValue(ContainerType::size_type index,intrusive_ptr<RightValue> newValue)2456 void LIST::setValue(ContainerType::size_type index, intrusive_ptr<RightValue> newValue) {
2457 assert(index<=this->container.size());
2458 this->container[index] = newValue;
2459 }
2460
addValue(intrusive_ptr<RightValue> newValue)2461 void LIST::addValue(intrusive_ptr<RightValue> newValue) {
2462 this->container.push_back(newValue);
2463 }
2464
insertValue(ContainerType::size_type position,intrusive_ptr<RightValue> newValue)2465 void LIST::insertValue(ContainerType::size_type position, intrusive_ptr<RightValue> newValue) {
2466 this->container.insert(this->container.begin()+position, newValue);
2467 }
2468
removeValue(ContainerType::size_type position)2469 void LIST::removeValue(ContainerType::size_type position) {
2470 this->container.erase(this->container.begin()+position);
2471 }
2472
size()2473 LIST::ContainerType::size_type LIST::size() const {
2474 return this->container.size();
2475 }
2476
dumpAsString(ostream & out)2477 ostream &MAT::dumpAsString(ostream &out) const {
2478 return out << this->theMatrix;
2479 }
2480
dumpAsString(ostream & out)2481 ostream &MatrixRowValue::dumpAsString(ostream &out) const {
2482 return out << "<matrix-row>";
2483 }
2484
dumpAsString(ostream & out)2485 ostream &LIST::dumpAsString(ostream &out) const {
2486 out << "[";
2487 bool first = true;
2488 for(ContainerType::const_iterator i = this->container.begin(); i!=this->container.end(); ++i) {
2489 /// does not work properly???? CoCoA::CheckForInterrupt("Printing LIST");
2490 if (first)
2491 first = false;
2492 else
2493 out << ", ";
2494 out << *i;
2495 (*i)->dumpRefCountAsString(out);
2496 }
2497 return out << "]";
2498 }
2499
CheckFieldName(const std::string & fieldName,const boost::intrusive_ptr<const AST::Expression> expr)2500 void RECORD::CheckFieldName(const std::string &fieldName, const boost::intrusive_ptr<const AST::Expression> expr)
2501 {
2502 if (!LexerNS::Lexer::isValidIdentifier(fieldName))
2503 {
2504 const bool IsKeyword = LexerNS::Lexer::isKeyword(fieldName);
2505 if (!IsKeyword)
2506 throw RuntimeException("Invalid field name \""+fieldName+"\"", expr);
2507 else
2508 throw RuntimeException("Invalid field name \""+fieldName+"\" - must not be a keyword", expr);
2509 }
2510 }
2511
CheckFieldName(const std::string & fieldName,const LexerNS::CharPointer & from,const LexerNS::CharPointer & to)2512 void RECORD::CheckFieldName(const std::string &fieldName, const LexerNS::CharPointer &from, const LexerNS::CharPointer &to)
2513 {
2514 if (!LexerNS::Lexer::isValidIdentifier(fieldName))
2515 {
2516 const bool IsKeyword = LexerNS::Lexer::isKeyword(fieldName);
2517 if (!IsKeyword)
2518 throw RuntimeException("Invalid field name \""+fieldName+"\"", from,to);
2519 else
2520 throw RuntimeException("Invalid field name \""+fieldName+"\" - must not be a keyword", from,to);
2521 }
2522 }
2523
2524
getFieldNoCheck(const string & fieldName)2525 intrusive_ptr<RightValue> RECORD::getFieldNoCheck(const string &fieldName) const {
2526 CheckFieldName(fieldName, CharPointer::Null, CharPointer::Null);
2527 MapType::const_iterator pos = this->fields.find(fieldName);
2528 return (pos!=this->fields.end()) ? pos->second : nullptr;
2529 }
2530
getField(const string & fieldName,const boost::intrusive_ptr<const AST::Expression> expr)2531 intrusive_ptr<RightValue> RECORD::getField(const string &fieldName, const boost::intrusive_ptr<const AST::Expression> expr) const
2532 {
2533 CheckFieldName(fieldName, expr);
2534 return getFieldNoCheck(fieldName);
2535 }
2536
getField(const string & fieldName,const LexerNS::CharPointer & from,const LexerNS::CharPointer & to)2537 intrusive_ptr<RightValue> RECORD::getField(const string &fieldName, const LexerNS::CharPointer &from, const LexerNS::CharPointer &to) const
2538 {
2539 CheckFieldName(fieldName, from,to);
2540 return getFieldNoCheck(fieldName);
2541 }
2542
setFieldNoCheck(const string & fieldName,intrusive_ptr<RightValue> newValue)2543 void RECORD::setFieldNoCheck(const string &fieldName, intrusive_ptr<RightValue> newValue) {
2544 MapType::iterator pos = this->fields.find(fieldName);
2545 if (pos!=this->fields.end())
2546 pos->second = newValue;
2547 else
2548 this->fields.insert(make_pair(fieldName, newValue));
2549 }
2550
setField(const string & fieldName,intrusive_ptr<RightValue> newValue,const boost::intrusive_ptr<const AST::Expression> expr)2551 void RECORD::setField(const string &fieldName, intrusive_ptr<RightValue> newValue, const boost::intrusive_ptr<const AST::Expression> expr)
2552 {
2553 CheckFieldName(fieldName, expr);
2554 setFieldNoCheck(fieldName, newValue);
2555 }
2556
2557
setField(const string & fieldName,intrusive_ptr<RightValue> newValue,const LexerNS::CharPointer & from,const LexerNS::CharPointer & to)2558 void RECORD::setField(const string &fieldName, intrusive_ptr<RightValue> newValue, const LexerNS::CharPointer &from, const LexerNS::CharPointer &to)
2559 {
2560 CheckFieldName(fieldName, from, to);
2561 setFieldNoCheck(fieldName, newValue);
2562 }
2563
needsToBeCopiedBeforeChanges()2564 bool RECORD::needsToBeCopiedBeforeChanges() const {
2565 if (this->getRefCount()>1)
2566 return true;
2567 for(MapType::const_iterator pos = this->fields.begin(); pos!=this->fields.end(); ++pos)
2568 if (pos->second->needsToBeCopiedBeforeChanges())
2569 return true;
2570 return false;
2571 }
2572
dumpAsString(ostream & out)2573 ostream &FUNCTION::dumpAsString(ostream &out) const {
2574 return out << "<function>";
2575 }
2576
dumpAsString(ostream & out)2577 ostream &RINGHOM::dumpAsString(ostream &out) const {
2578 return out << this->theRingHom;
2579 }
2580
formatExpectedArgs(int found,int min,int max)2581 string WrongNumberOfArgumentsException::formatExpectedArgs(int found, int min, int max) {
2582 assert(min<=max);
2583 string msg("Wrong number of arguments; found: "+boost::lexical_cast<std::string>(found)+", expecting: ");
2584 if (min==max)
2585 return msg+lexical_cast<string>(min);
2586 return msg+lexical_cast<string>(min) + ".." + lexical_cast<string>(max);
2587 }
2588
UserDefinedFunction(RuntimeEnvironment * runtimeEnv,const intrusive_ptr<const FunctionDeclaration> fnDecl)2589 UserDefinedFunction::UserDefinedFunction(RuntimeEnvironment *runtimeEnv, const intrusive_ptr<const FunctionDeclaration> fnDecl) :
2590 fnDecl(fnDecl),
2591 fp(runtimeEnv->getCurrentFrame())
2592 {
2593 assert(this->fnDecl);
2594 BOOST_FOREACH(const Import &import, fnDecl->imports)
2595 if (import.type==Import::IT_BYVALUE) {
2596 assert(this->capturedValues.size()==static_cast<std::vector<boost::intrusive_ptr<RightValue> >::size_type>(import.byValueIndex));
2597 this->capturedValues.push_back(import.expId->evalAs<RightValue>(runtimeEnv));
2598 }
2599 }
2600
getCurrentFunctionFrame()2601 Frame *RuntimeEnvironment::getCurrentFunctionFrame() {
2602 Frame *f = this->currentFrame;
2603 assert(f>getTopLevelFrame());
2604 for(;;) {
2605 if (f->userdefinedFun)
2606 return f;
2607 --f;
2608 assert(f>getTopLevelFrame());
2609 }
2610 }
2611
getCurrentFunctionFrameOrNull()2612 Frame *RuntimeEnvironment::getCurrentFunctionFrameOrNull() {
2613 Frame *f = this->currentFrame;
2614 for(;;) {
2615 if (f==getTopLevelFrame())
2616 return nullptr;
2617 if (f->userdefinedFun)
2618 return f;
2619 --f;
2620 }
2621 }
2622
eval(const intrusive_ptr<const InvocationExpression> invocationExpression,RuntimeEnvironment * runtimeEnv)2623 intrusive_ptr<RightValue> UserDefinedFunction::eval(const intrusive_ptr<const InvocationExpression> invocationExpression, RuntimeEnvironment *runtimeEnv) const {
2624 const vector<Param>::size_type nParameters = this->fnDecl->params.size();
2625 const vector<Param>::size_type nMandatoryParameters = static_cast<vector<Param>::size_type>(this->fnDecl->nMandatoryParameters);
2626 intrusive_ptr<LIST> ellipsisValues(new LIST());
2627 const bool calledWithEllipsis = invocationExpression->ellipsis;
2628 const bool receivesEllipsis = this->fnDecl->thereIsEllipsis;
2629 if (calledWithEllipsis) {
2630 const Frame * const f = runtimeEnv->getCurrentFunctionFrame();
2631 assert(f->varSlots.size());
2632 const VariableSlot &vs = f->varSlots.front();
2633 assert(vs.isArgs());
2634 ellipsisValues = intrusive_ptr_cast<LIST>(vs.value);
2635 if (!receivesEllipsis) {
2636 const LIST::ContainerType::size_type nArgs = ellipsisValues->size();
2637 if (nArgs<nMandatoryParameters || nArgs>nParameters)
2638 throw WrongNumberOfArgumentsException(invocationExpression, nArgs, nMandatoryParameters, nParameters);
2639 BOOST_FOREACH(const Param ¶m, this->fnDecl->params)
2640 if (param.byRef)
2641 throw RuntimeException("Cannot use ellipsis on functions/procedures expecting by-ref parameters", invocationExpression);
2642 }
2643 } else { // called with actual arguments (that is, not "...")
2644 const vector<Argument>::size_type nArgs = invocationExpression->args.size();
2645 if (receivesEllipsis) {
2646 BOOST_FOREACH(const Argument &arg, invocationExpression->args)
2647 if (arg.byRef)
2648 throw RuntimeException("Cannot pass by-ref arguments to functions/procedures expecting a variable number of arguments", invocationExpression);
2649 } else
2650 if (nArgs<nMandatoryParameters || nArgs>nParameters)
2651 throw WrongNumberOfArgumentsException(invocationExpression, nArgs, nMandatoryParameters, nParameters);
2652 }
2653 vector<VariableSlot> slots;
2654 if (!receivesEllipsis) {
2655 if (calledWithEllipsis) {
2656 const LIST::ContainerType::size_type nArgs = ellipsisValues->size();
2657 for(vector<Param>::size_type a=0; a<nParameters; ++a) {
2658 if (a<nArgs) {
2659 const intrusive_ptr<RightValue> v = ellipsisValues->getValue(a);
2660 assert(v);
2661 slots.push_back(VariableSlot(v, VariableSlot::VSF_None));
2662 } else {
2663 assert(this->fnDecl->params[a].opt);
2664 slots.push_back(VariableSlot(VoidValue::theInstance, VariableSlot::VSF_None));
2665 }
2666 }
2667 } else { // don't receive ellipsis and is not called with ellipsis
2668 const vector<Argument>::size_type nArgs = invocationExpression->args.size();
2669 for(vector<Param>::size_type a=0; a<nParameters; ++a) {
2670 const Param ¶m = this->fnDecl->params[a];
2671 if (a<nArgs)
2672 slots.push_back(VariableSlot(runtimeEnv->evalArg(invocationExpression->args[a], param.byRef ? RuntimeEnvironment::EVAL_BY_REF:RuntimeEnvironment::EVAL_BY_VALUE), VariableSlot::VSF_None));
2673 else {
2674 assert(param.opt);
2675 slots.push_back(VariableSlot(VoidValue::theInstance, VariableSlot::VSF_None));
2676 }
2677 }
2678 }
2679 } else { // receives ellipsis
2680 slots.push_back(VariableSlot(ellipsisValues, VariableSlot::VSF_Args));
2681 if (!calledWithEllipsis) {
2682 const vector<Argument>::size_type nArgs = invocationExpression->args.size();
2683 for(vector<Argument>::size_type a=0; a<nArgs; ++a)
2684 ellipsisValues->addValue(runtimeEnv->evalArg(invocationExpression->args[a], RuntimeEnvironment::EVAL_BY_VALUE)->asRightValue());
2685 }
2686 }
2687 Frame *frame = runtimeEnv->pushFrame(this->fp, invocationExpression, this->fnDecl, this);
2688 BOOST_SCOPE_EXIT( (runtimeEnv) ) {
2689 runtimeEnv->popFrame();
2690 } BOOST_SCOPE_EXIT_END
2691 const std::map<std::string, int>::size_type localSize = this->fnDecl->localNames.size();
2692 assert(slots.size()<=localSize);
2693 while (slots.size()<localSize)
2694 slots.push_back(VariableSlot(VoidValue::theInstance, VariableSlot::VSF_None));
2695 frame->varSlots.swap(slots);
2696 #ifdef VERBOSE_RUNTIME_DEBUG
2697 {
2698 cout << "\n======\nUserDefinedFunction::eval, frames->varSlots:";
2699 int i = 0;
2700 BOOST_FOREACH(const VariableSlot &vs, frame->varSlots)
2701 cout << "[" << i++ << "].value = " << vs.value << endl;
2702 cout << "======\n";
2703 }
2704 #endif // #ifdef VERBOSE_RUNTIME_DEBUG
2705 try {
2706 this->fnDecl->statements->execute(runtimeEnv);
2707 if (this->fnDecl->thereAreReturnsWithExpr) {
2708 const CharPointer p = this->fnDecl->statements->getEnd();
2709 throw RuntimeException("A function must explicitly Return a value", p, p);
2710 }
2711 } catch (const Return &ret) {
2712 return ret.value;
2713 } catch (const Break &) {
2714 assert(false);
2715 } catch (const Continue &) {
2716 assert(false);
2717 } catch (RuntimeException &re) {
2718 if (re.snapshot.size()==0)
2719 re.snapshot = runtimeEnv->takeSnapshot();
2720 throw;
2721 }
2722 return VoidValue::theInstance;
2723 }
2724
eval(const intrusive_ptr<const InvocationExpression> invocationExpression,RuntimeEnvironment * runtimeEnv)2725 intrusive_ptr<RightValue> RINGHOM::eval(const intrusive_ptr<const InvocationExpression> invocationExpression, RuntimeEnvironment *runtimeEnv) const {
2726 intrusive_ptr<RightValue> argValue;
2727 CharPointer argBegin(invocationExpression->getBegin());
2728 CharPointer argEnd(invocationExpression->getEnd());
2729 if (invocationExpression->ellipsis) {
2730 argBegin = invocationExpression->tokEllipsis->getBegin();
2731 argEnd = invocationExpression->tokEllipsis->getEnd();
2732 const Frame * const f = runtimeEnv->getCurrentFunctionFrame();
2733 assert(f->varSlots.size());
2734 const VariableSlot &vs = f->varSlots.front();
2735 assert(vs.isArgs());
2736 intrusive_ptr<LIST> ellipsisValues(intrusive_ptr_cast<LIST>(vs.value));
2737 const LIST::ContainerType::size_type nArgs = ellipsisValues->size();
2738 if (nArgs!=1)
2739 throw WrongNumberOfArgumentsException(invocationExpression, nArgs, 1);
2740 argValue = ellipsisValues->getValue(0)->asRightValue();
2741 } else {
2742 const Argument &arg = invocationExpression->args.front();
2743 argBegin = arg.exp->getBegin();
2744 argEnd = arg.exp->getEnd();
2745 const vector<Argument>::size_type nArgs = invocationExpression->args.size();
2746 if (nArgs!=1)
2747 throw WrongNumberOfArgumentsException(invocationExpression, nArgs, 1);
2748 argValue = intrusive_ptr_cast<RightValue>(runtimeEnv->evalArg(arg, RuntimeEnvironment::EVAL_BY_VALUE));
2749 }
2750 try {
2751 if (intrusive_ptr<RINGELEM> poly = dynamic_pointer_cast<RINGELEM>(argValue))
2752 return new RINGELEM(this->theRingHom(poly->theRingElem));
2753 if (intrusive_ptr<INT> N = dynamic_pointer_cast<INT>(argValue))
2754 return new RINGELEM(this->theRingHom(N->theBigInt));
2755 if (intrusive_ptr<RAT> q = dynamic_pointer_cast<RAT>(argValue))
2756 return new RINGELEM(this->theRingHom(q->theBigRat));
2757 else if (intrusive_ptr<RINGHOM> hom = dynamic_pointer_cast<RINGHOM>(argValue))
2758 return new RINGHOM(this->theRingHom(hom->theRingHom));
2759 throw WrongTypeException(
2760 RINGELEM::type->name + " or " +
2761 INT::type->name + " or " +
2762 RAT::type->name + " or " +
2763 RINGHOM::type->name,
2764 argValue->getType()->name,
2765 argBegin,
2766 argEnd);
2767 }
2768 catch (const ErrorInfo& err)
2769 {
2770 runtimeEnv->announceCLE(err);
2771 throw RuntimeException(message_forC5(err), invocationExpression->getBegin(), invocationExpression->getEnd());
2772 }
2773 catch (const InterruptReceived& /*intr*/)
2774 {
2775 throw InterruptException(invocationExpression->getBegin(), invocationExpression->getEnd());
2776 }
2777
2778 }
2779
eval(const intrusive_ptr<const InvocationExpression> invocationExpression,RuntimeEnvironment * runtimeEnv)2780 intrusive_ptr<RightValue> BuiltInFunction::eval(const intrusive_ptr<const InvocationExpression> invocationExpression, RuntimeEnvironment *runtimeEnv) const {
2781 #ifdef C5IDE
2782 Interpreter::InterpreterStatus prevStatus = runtimeEnv->interpreter->UpdateStatusStartingBuiltIn();
2783 BOOST_SCOPE_EXIT( (runtimeEnv)(prevStatus) ) {
2784 runtimeEnv->interpreter->UpdateStatusEndingBuiltIn(prevStatus);
2785 } BOOST_SCOPE_EXIT_END
2786 #endif // #ifdef C5IDE
2787 try {
2788 if (invocationExpression->ellipsis) {
2789 const Frame * const f = runtimeEnv->getCurrentFunctionFrame();
2790 assert(f->varSlots.size());
2791 const VariableSlot &vs = f->varSlots.front();
2792 assert(vs.isArgs());
2793 intrusive_ptr<LIST> ellipsisValues(intrusive_ptr_cast<LIST>(vs.value));
2794 LIST::ContainerType::size_type nArgs = ellipsisValues->size();
2795 vector<Argument> args;
2796 CharPointer begin(invocationExpression->tokEllipsis->getBegin());
2797 CharPointer end(invocationExpression->tokEllipsis->getEnd());
2798 for(LIST::ContainerType::size_type a=0; a<nArgs; ++a)
2799 args.push_back(Argument(false, new FakeExpression(ellipsisValues->getValue(a), begin, end), true));
2800 boost::shared_ptr<Token> noEllipsis;
2801 const intrusive_ptr<const InvocationExpression> fakeInvocationExpression(new InvocationExpression(invocationExpression->targetExp, noEllipsis, args, invocationExpression->getEnd(), invocationExpression->packageName));
2802 return this->function(fakeInvocationExpression, runtimeEnv);
2803 }
2804 return this->function(invocationExpression, runtimeEnv);
2805 }
2806 catch (const ErrorInfo& err)
2807 {
2808 runtimeEnv->announceCLE(err);
2809 throw RuntimeException(message_forC5(err), invocationExpression);
2810 }
2811 catch (const InterruptReceived& /*intr*/)
2812 {
2813 throw InterruptException(invocationExpression);
2814 }
2815 }
2816
obtainOwnership()2817 void LeftValue::obtainOwnership() {
2818 const intrusive_ptr<VariableName> base = this->getBase();
2819 Frame * const f = base->framePointer.toNonNullCheckedPointer(base->expId);
2820 if (base->slotIndex<0) {
2821 assert(f==base->runtimeEnvironment->getTopLevelFrame());
2822 base->slotIndex = base->runtimeEnvironment->slotFor(base->expId->identifier);
2823 if (base->slotIndex<0)
2824 return;
2825 }
2826 assert(static_cast<vector<VariableSlot>::size_type>(base->slotIndex)<f->varSlots.size());
2827 assert(f->varSlots[base->slotIndex].value);
2828 VariableSlot &varSlot = f->varSlots[base->slotIndex];
2829 RightValue * const target = intrusive_ptr_cast<RightValue>(varSlot.value).get();
2830 if (target->needsToBeCopiedBeforeChanges())
2831 varSlot.value = target->clone();
2832 }
2833
checkIndex(const intrusive_ptr<const RightValue> v,const intrusive_ptr<const Expression> originalExp)2834 LIST::ContainerType::size_type LIST::checkIndex(const intrusive_ptr<const RightValue> v, const intrusive_ptr<const Expression> originalExp) const {
2835 if (const intrusive_ptr<const INT> NV = dynamic_pointer_cast<const INT>(v)) {
2836 const BigInt N(NV->theBigInt);
2837 long l;
2838 if (!IsConvertible(l, N) || l<=0 || static_cast<ContainerType::size_type>(l)>this->size())
2839 throw IndexOutOfRangeException(N, this->size(), originalExp);
2840 return l-1;
2841 }
2842 throw WrongTypeException(
2843 INT::type->name,
2844 v->getType()->name,
2845 originalExp);
2846 }
2847
2848 namespace {
printErrors(intrusive_ptr<ErrorReporter> errorReporter,intrusive_ptr<OSTREAM> output)2849 void printErrors(intrusive_ptr<ErrorReporter> errorReporter, intrusive_ptr<OSTREAM> output) {
2850 assert(errorReporter);
2851 const int nErrors = errorReporter->getErrorCount();
2852 const int nWarnings = errorReporter->getWarningCount();
2853 if (nErrors || nWarnings)
2854 output->print("Got ")->print(lexical_cast<string>(nErrors))->print(" error(s) and ")->print(lexical_cast<string>(nWarnings))->print(" warning(s).\n");
2855 }
2856
execute(intrusive_ptr<Statement> s,RuntimeEnvironment * re,intrusive_ptr<ErrorReporter> errorReporter)2857 void execute(intrusive_ptr<Statement> s, RuntimeEnvironment *re, intrusive_ptr<ErrorReporter> errorReporter) {
2858 assert(re);
2859 #ifdef VERBOSE_RUNTIME_DEBUG
2860 cout << "Parsed statement = " << s << "\n";
2861 #endif // #ifdef VERBOSE_RUNTIME_DEBUG
2862 CheckNamesVisitor cnv(re, errorReporter);
2863 s->accept(&cnv);
2864 #ifdef VERBOSE_RUNTIME_DEBUG
2865 DumpAsTreeVisitor v(cout);
2866 s->accept(&v);
2867 #endif // #ifdef VERBOSE_RUNTIME_DEBUG
2868 if (!errorReporter->getErrorCount())
2869 s->execute(re);
2870 }
2871 }
2872
2873 #ifdef C5IDE
run(IDE::Console * console)2874 int Interpreter::run(IDE::Console *console) {
2875 #else // #ifdef C5IDE
2876 int Interpreter::run() {
2877 #endif // #ifdef C5IDE
2878 #ifdef C5IDE
2879 assert(this->status==IS_WAITING_FOR_COMMAND);
2880 loadPackages(console);
2881 #endif // #ifdef C5IDE
2882 try
2883 {
2884 intrusive_ptr<Lexer> lexer = intrusive_ptr<Lexer>(new Lexer(this->errorReporter, this->lineProvider, this->warnAboutCocoa5, true));
2885 intrusive_ptr<Parser> parser(new Parser(lexer));
2886 double CmdStartTime = 0.0;
2887 bool StmtWasNOP = false; // set to "false" for correct first-time behaviour
2888 for(;;)
2889 {
2890 #ifdef C5IDE
2891 this->status = IS_WAITING_FOR_COMMAND;
2892 #endif // #ifdef C5IDE
2893 if (!StmtWasNOP && GlobalStatusLogStream)
2894 {
2895 const double CpuNow=CpuTime();
2896 GlobalStatusLogStream << 'W' << std::round(10*(CpuNow-CmdStartTime))/10 << std::endl;
2897 }
2898
2899 intrusive_ptr<Statement> s;
2900 try {
2901 this->errorReporter->resetErrorCounts();
2902 lexer->startingTopLevelStatement();
2903 Token t = lexer->getToken(parser->getStatus());
2904 if (t.getType()==TT_EOF)
2905 return EXIT_SUCCESS;
2906 lexer->ungetToken(t);
2907 s = parser->parseTopLevelStatement();
2908 if (!s || this->errorReporter->getErrorCount())
2909 continue;
2910 } catch (const UnexpectedTokenException &ete) {
2911 lexer->reportError(ete.reason, ete.found.getBegin(), ete.found.getEnd(), false);
2912 if (ete.found.getType()==TT_EOF)
2913 return EXIT_FAILURE;
2914 if (ete.needsRecovery)
2915 parser->tryToRecover(ete.from);
2916 continue;
2917 } catch (const ExceptionWithSourcePosition &ewsp) {
2918 lexer->reportError(ewsp.reason, ewsp.from, ewsp.to, false);
2919 if (ewsp.needsRecovery)
2920 parser->tryToRecover(ewsp.from);
2921 continue;
2922 } catch (const BaseException &e) {
2923 lexer->reportError(e.reason);
2924 continue;
2925 }
2926 assert(s && this->errorReporter->getErrorCount()==0);
2927
2928 StmtWasNOP = s->IamEmptyStmt();
2929 if (!StmtWasNOP) // if NOP, do not wastefully update status to "running" (for a microsecond?)
2930 {
2931 try {
2932 #ifdef C5IDE
2933 this->status = IS_RUNNING;
2934 this->runtimeEnvironment.getOutputStream()->flush(); // this allows the GUI thread to update the status label
2935 #endif // #ifdef C5IDE
2936 if (GlobalStatusLogStream)
2937 {
2938 GlobalStatusLogStream << 'R' << std::endl;
2939 CmdStartTime = CpuTime();
2940 }
2941 CoCoA::GetAndResetSignalReceived(); // discard any pending signals
2942 execute(s, &(this->runtimeEnvironment), this->errorReporter);
2943 } catch (const Ciao &) {
2944 #ifdef C5IDE
2945 this->status = IS_ENDED;
2946 #endif // #ifdef C5IDE
2947 return EXIT_SUCCESS;
2948 } catch (const InterruptException& intr) {
2949 this->errorReporter->reportInterrupt(intr);
2950 } catch (const RuntimeException &re) {
2951 this->errorReporter->reportError(re);
2952 }
2953 // catch (const CoCoA::InterruptReceived&) { /* don't know how to handle this ==> ignore it */ }
2954 //??? { this->errorReporter->reportError(InterruptException(0)); } // BUG BUG BUG ??? what should the arg be???
2955 }
2956 }
2957 } catch (const BaseException &e) {
2958 cout << "***ERROR*** UNCAUGHT Interpreter BaseException exc-reason=" << e.reason << endl;
2959 } catch (const ErrorInfo& err) {
2960 cout << "***ERROR*** UNCAUGHT CoCoA error" << endl;
2961 ANNOUNCE(cout, err);
2962 } catch (const std::exception& exc) {
2963 cout << "***ERROR*** UNCAUGHT std::exception: " << exc.what() << endl;
2964 } catch(...) {
2965 cout << "***ERROR*** UNCAUGHT UNKNOWN EXCEPTION" << endl;
2966 }
2967 return EXIT_FAILURE;
2968 }
2969
2970 void Interpreter::readAndExecute(const std::string &filename, bool calledFromMain, bool immediateExecution, long FromLine, long FromChar, long ToLine, long ToChar) {
2971 struct stat statbuf;
2972 if (stat(filename.c_str(), &statbuf)) {
2973 if (errno==ENOENT)
2974 throw BaseException("Cannot find a file named \""+filename+"\"");
2975 throw BaseException("Cannot read \""+filename+"\" information; system-error: "+strerror(errno));
2976 }
2977 FilePair pair(statbuf.st_dev, statbuf.st_ino);
2978 if (!this->sourcedFiles.insert(pair).second)
2979 throw BaseException("Files cannot be recursively Source-d");
2980 Interpreter &This = *this;
2981 BOOST_SCOPE_EXIT( (&This)(&pair) ) {
2982 This.sourcedFiles.erase(pair);
2983 } BOOST_SCOPE_EXIT_END
2984 try {
2985 boost::intrusive_ptr<LineProvider> SourceText;
2986 if (FromLine < 0) SourceText = new FileLineProvider(filename);
2987 else SourceText = new FileRegionLineProvider(filename, FromLine,FromChar, ToLine,ToChar);
2988 intrusive_ptr<Lexer> lexer = new Lexer(this->errorReporter, SourceText, this->warnAboutCocoa5, false);
2989 intrusive_ptr<Parser> parser(new Parser(lexer));
2990 vector<intrusive_ptr<Statement> > statements;
2991 for(;;) {
2992 intrusive_ptr<Statement> s;
2993 try {
2994 lexer->startingTopLevelStatement();
2995 Token t = lexer->getToken(parser->getStatus());
2996 if (t.getType()==TT_EOF)
2997 break;
2998 lexer->ungetToken(t);
2999 s = parser->parseTopLevelStatement();
3000 } catch (const UnexpectedTokenException &ete) {
3001 lexer->reportError(ete.reason, ete.found.getBegin(), ete.found.getEnd(), false);
3002 this->errorReporter->outputStream->newline();
3003 if (ete.found.getType()==TT_EOF) {
3004 if (calledFromMain) {
3005 printErrors(this->errorReporter, this->runtimeEnvironment.getOutputStream());
3006 return;
3007 }
3008 throw BaseException("Unexpected End-Of-Input while reading \""+filename+"\"");
3009 }
3010 if (ete.needsRecovery)
3011 parser->tryToRecover(ete.from);
3012 } catch (const ExceptionWithSourcePosition &ewsp) {
3013 lexer->reportError(ewsp.reason, ewsp.from, ewsp.to, false);
3014 this->errorReporter->outputStream->newline();
3015 if (ewsp.needsRecovery)
3016 parser->tryToRecover(ewsp.from);
3017 }
3018 if (s) {
3019 if (immediateExecution && this->errorReporter->getErrorCount()==0) {
3020 try {
3021 execute(s, &(this->runtimeEnvironment), this->errorReporter);
3022 } catch (const InterruptException &) {
3023 throw;
3024 } catch (const RuntimeException &re) {
3025 this->errorReporter->reportError(re);
3026 this->errorReporter->outputStream->newline();
3027 }
3028 } else
3029 statements.push_back(s);
3030 }
3031 }
3032 try {
3033 BOOST_FOREACH(intrusive_ptr<Statement> s, statements) {
3034 if (this->errorReporter->getErrorCount())
3035 break;
3036 execute(s, &(this->runtimeEnvironment), this->errorReporter);
3037 }
3038 } catch (const InterruptException &) {
3039 throw;
3040 } catch (const RuntimeException &re) {
3041 this->errorReporter->reportError(re);
3042 this->errorReporter->outputStream->newline();
3043 }
3044 } catch (BaseException &) {
3045 throw;
3046 } catch (const std::exception &e) {
3047 throw BaseException(string(e.what())+"\nWhile trying to read and execute \""+filename+"\"");
3048 }
3049 if (calledFromMain)
3050 printErrors(this->errorReporter, this->runtimeEnvironment.getOutputStream());
3051 else if (this->errorReporter->getErrorCount())
3052 throw BaseException("Read and execution of the source file \""+filename+"\" failed");
3053 }
3054
3055 bool UserDefinedFunction::canBeCalledWith(int nArg) {
3056 const intrusive_ptr<const FunctionDeclaration> fnDecl = this->fnDecl;
3057 return fnDecl->thereIsEllipsis || (nArg>=fnDecl->nMandatoryParameters && static_cast<vector<Param>::size_type>(nArg)<=fnDecl->params.size());
3058 }
3059
3060 bool BuiltInFunction::canBeCalledWith(int nArg) {
3061 return this->arityCheck(nArg);
3062 }
3063
3064 bool RINGHOM::canBeCalledWith(int nArg) {
3065 return nArg==1;
3066 }
3067
3068 intrusive_ptr<VariableName> PackageValue::toVariableName(RuntimeEnvironment *runtimeEnv, const string &memberName, const Token &tokMemberName) {
3069 const int index = runtimeEnv->slotFor(this->prefix+memberName);
3070 if (index<0)
3071 throw RuntimeException("Package "+this->pkgName+" doesn't have a member named "+memberName, tokMemberName);
3072 return new VariableName(runtimeEnv, runtimeEnv->getTopLevelFrame(), index, new Identifier(tokMemberName));
3073 }
3074
3075
3076 bool RuntimeEnvironment::CheckArity(int arity, map<string, int>::const_iterator pos) const
3077 {
3078 if (arity < 0) return true;
3079
3080 const VariableSlot &vs = getTopLevelFrame()->varSlots[pos->second];
3081 intrusive_ptr<Value> v = vs.value;
3082 if (!v) return false;
3083 if (vs.isPackage())
3084 {
3085 const intrusive_ptr<const VariableName> vn = intrusive_ptr_cast<VariableName>(v);
3086 const int index = vn->expId->varData.index;
3087 assert(vn->expId->varData.depth==StaticEnv::TOP_LEVEL);
3088 assert(index>=0 && static_cast<vector<VariableSlot>::size_type>(index)<getTopLevelFrame()->varSlots.size());
3089 v = getTopLevelFrame()->varSlots[index].value;
3090 if (!v) return false;
3091 }
3092 if (const intrusive_ptr<FUNCTION> fv = dynamic_pointer_cast<FUNCTION>(v))
3093 {
3094 if (!fv->canBeCalledWith(arity))
3095 return false;
3096 } else
3097 return false;
3098 return true;
3099 }
3100
3101 void RuntimeEnvironment::collectSimilarlyNamedIdentifiers(const string &id, int arity, vector<string> &NearMatches, bool &thereIsAnExactMatch) const
3102 {
3103 const int maxDistance = maximumDistanceForSimilarIdentifiers(id);
3104 vector<string> dist0, dist1, dist2, dist3plus, DifferentArity;
3105 for (map<string, int>::const_iterator pos = this->topLevelIdentifiers.begin(); pos!=this->topLevelIdentifiers.end(); ++pos)
3106 {
3107 if (pos->first==id)
3108 {
3109 if (!getTopLevelFrame()->varSlots[pos->second].value)
3110 continue;
3111 thereIsAnExactMatch = true;
3112 return;
3113 }
3114 const int ldist = levenshteinDistance(id, pos->first);
3115 if (ldist>maxDistance) continue;
3116
3117 if (!CheckArity(arity, pos)) { DifferentArity.push_back(pos->first); continue; }
3118 if (ldist == 0) { dist0.push_back(pos->first); continue; }
3119 if (ldist == 1) { dist1.push_back(pos->first); continue; }
3120 if (ldist == 2) { dist2.push_back(pos->first); continue; }
3121 dist3plus.push_back(pos->first);
3122 }
3123 // Sort each category of names into alphabetical order
3124 sort(dist0.begin(), dist0.end());
3125 sort(dist1.begin(), dist1.end());
3126 sort(dist2.begin(), dist2.end());
3127 sort(dist3plus.begin(), dist3plus.end());
3128 sort(DifferentArity.begin(), DifferentArity.end());
3129 // Now output the names found in increasing order of remoteness
3130 NearMatches.insert(NearMatches.end(), dist0.begin(), dist0.end());
3131 NearMatches.insert(NearMatches.end(), dist1.begin(), dist1.end());
3132 NearMatches.insert(NearMatches.end(), dist2.begin(), dist2.end());
3133 NearMatches.insert(NearMatches.end(), dist3plus.begin(), dist3plus.end());
3134 NearMatches.insert(NearMatches.end(), DifferentArity.begin(), DifferentArity.end());
3135 if (id=="Z") NearMatches.push_back("ZZ");
3136 if (id=="Q") NearMatches.push_back("QQ");
3137 }
3138
3139 ////////////// Value::from implementations ///////////////////////////////
3140
3141 //??? template<typename T> ???
3142 boost::intrusive_ptr<RECORD> Value::from(const factorization<RingElem>& f)
3143 {
3144 intrusive_ptr<RECORD> facsC5(new RECORD);
3145 facsC5->setFieldNoCheck("factors", Value::from(f.myFactors()));
3146 facsC5->setFieldNoCheck("multiplicities", Value::from(f.myMultiplicities()));
3147 facsC5->setFieldNoCheck("RemainingFactor", Value::from(f.myRemainingFactor()));
3148 return facsC5;
3149 }
3150
3151 boost::intrusive_ptr<RECORD> Value::from(const factorization<BigInt>& f)
3152 {
3153 intrusive_ptr<RECORD> facsC5(new RECORD);
3154 facsC5->setFieldNoCheck("factors", Value::from(f.myFactors()));
3155 facsC5->setFieldNoCheck("multiplicities", Value::from(f.myMultiplicities()));
3156 facsC5->setFieldNoCheck("RemainingFactor", Value::from(f.myRemainingFactor()));
3157 return facsC5;
3158 }
3159
3160 boost::intrusive_ptr<RECORD> Value::from(const HPSeries &s)
3161 {
3162 intrusive_ptr<RECORD> r(new RECORD);
3163 r->setFieldNoCheck("num", Value::from(num(s)));
3164 r->setFieldNoCheck("DenFactors", Value::from(DenFactors(s)));
3165 return r;
3166 }
3167
3168 boost::intrusive_ptr<LIST> Value::from(const degree &x)
3169 { return Value::from(DegreeToVec(x)); }
3170
3171 boost::intrusive_ptr<LIST> Value::from(const QuasiPoly &x)
3172 { return Value::from(constituents(x)); }
3173
3174 ////////////// Value::from implementations (end) ////////////////////////
3175
3176 }
3177 // namespace InterpreterNS
3178
3179 namespace AST {
3180
3181 using namespace std;
3182 using namespace boost;
3183 using namespace CoCoA::InterpreterNS;
3184
IntLiteral(const Token & t)3185 IntLiteral::IntLiteral(const Token &t) :
3186 LiteralExpression(t.getBegin(), t.getEnd()),
3187 theBigInt(INT::from(BigIntFromString(t.lexeme())))
3188 {
3189 }
3190
FloatLiteral(const Token & t)3191 FloatLiteral::FloatLiteral(const Token &t) :
3192 LiteralExpression(t.getBegin(), t.getEnd()),
3193 theBigRat(RAT::simplifiedValueFrom(buildTheRational(t)))
3194 {
3195 }
3196
StringLiteral(const CharPointer & beginSourcePosition,const CharPointer & endSourcePosition,const string & unescapedString)3197 StringLiteral::StringLiteral(const CharPointer &beginSourcePosition, const CharPointer & endSourcePosition, const string &unescapedString) :
3198 LiteralExpression(beginSourcePosition, endSourcePosition),
3199 theString(STRING::from(unescapedString))
3200 {
3201 }
3202
BoolLiteral(const CharPointer & beginSourcePosition,const CharPointer & endSourcePosition,TokenType tokenType)3203 BoolLiteral::BoolLiteral(const CharPointer &beginSourcePosition, const CharPointer & endSourcePosition, TokenType tokenType) :
3204 LiteralExpression(beginSourcePosition, endSourcePosition),
3205 theBool(BOOL::from(tokenType==LexerNS::TT_TRUE))
3206 {
3207 assert(tokenType==LexerNS::TT_TRUE || tokenType==LexerNS::TT_FALSE);
3208 }
3209
checkNumberOfArgs(int n)3210 int InvocationExpression::checkNumberOfArgs(int n) const {
3211 const int nArgs = this->args.size();
3212 if (nArgs!=n)
3213 throw WrongNumberOfArgumentsException(this, nArgs, n);
3214 return nArgs;
3215 }
3216
checkNumberOfArgs(int nMin,int nMax)3217 int InvocationExpression::checkNumberOfArgs(int nMin, int nMax) const {
3218 const int nArgs = this->args.size();
3219 if (nArgs<nMin || nArgs>nMax)
3220 throw WrongNumberOfArgumentsException(this, nArgs, nMin, nMax);
3221 return nArgs;
3222 }
3223
collectSimilarlyNamedIdentifiers(const string & id,int arity,vector<string> & NearMatches,bool & thereIsAnExactMatch)3224 void StaticEnv::collectSimilarlyNamedIdentifiers(const string &id, int arity, vector<string> &NearMatches, bool &thereIsAnExactMatch) const {
3225 if (this->runtimeEnvironment) {
3226 assert(!this->parent);
3227 this->runtimeEnvironment->collectSimilarlyNamedIdentifiers(id, arity, NearMatches, thereIsAnExactMatch);
3228 return;
3229 }
3230 assert(this->parent);
3231 const int maxDistance = maximumDistanceForSimilarIdentifiers(id);
3232 for(IdMap::const_iterator pos = this->identifierMap.begin(); pos!=this->identifierMap.end(); ++pos) {
3233 if (pos->second.depth<0)
3234 continue;
3235 if (pos->first==id) {
3236 thereIsAnExactMatch = true;
3237 return;
3238 }
3239 if (levenshteinDistance(id, pos->first)<=maxDistance)
3240 NearMatches.push_back(pos->first);
3241 }
3242 if (!thereIsAnExactMatch)
3243 this->parent->collectSimilarlyNamedIdentifiers(id, arity, NearMatches, thereIsAnExactMatch);
3244 }
3245
3246 namespace {
dontKnow(const intrusive_ptr<const Expression> e)3247 intrusive_ptr<Value> dontKnow(const intrusive_ptr<const Expression> e) {
3248 throw RuntimeException("I don't know (yet) how to evaluate this expression", e->getBegin(), e->getEnd());
3249 }
3250 }
3251
implEval(RuntimeEnvironment * runtimeEnv)3252 intrusive_ptr<Value> ColonExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3253 return runtimeEnv->binaryOperatorDispatch(
3254 this->leftExp->evalAs<RightValue>(runtimeEnv),
3255 this->rightExp->evalAs<RightValue>(runtimeEnv),
3256 RuntimeEnvironment::opColonMap,
3257 this->beginOperatorSourcePosition,
3258 this->endOperatorSourcePosition);
3259 }
3260
implEval(RuntimeEnvironment *)3261 intrusive_ptr<Value> ModuloExpression::implEval(RuntimeEnvironment * /*runtimeEnv*/) const {
3262 return dontKnow(this);
3263 }
3264
implEval(RuntimeEnvironment * runtimeEnv)3265 intrusive_ptr<Value> BackwardCompatibleExp::implEval(RuntimeEnvironment *runtimeEnv) const {
3266 return this->innerExp->eval(runtimeEnv);
3267 }
3268
implEval(RuntimeEnvironment *)3269 intrusive_ptr<Value> ScopedExpression::implEval(RuntimeEnvironment *) const {
3270 return dontKnow(this);
3271 }
3272
implEval(RuntimeEnvironment * runtimeEnv)3273 intrusive_ptr<Value> UnaryPlusExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3274 return this->exp->evalAs<RightValue>(runtimeEnv);
3275 }
3276
implEval(RuntimeEnvironment * const runtimeEnv)3277 intrusive_ptr<Value> UnaryMinusExpression::implEval(RuntimeEnvironment * const runtimeEnv) const {
3278 return this->exp->evalAs<RightValue>(runtimeEnv)->unaryMinus(this->getBegin(), runtimeEnv);
3279 }
3280
implEval(RuntimeEnvironment *)3281 intrusive_ptr<Value> IntLiteral::implEval(RuntimeEnvironment *) const {
3282 return this->theBigInt;
3283 }
3284
implEval(RuntimeEnvironment *)3285 intrusive_ptr<Value> FloatLiteral::implEval(RuntimeEnvironment *) const {
3286 return this->theBigRat;
3287 }
3288
implEval(RuntimeEnvironment *)3289 intrusive_ptr<Value> BoolLiteral::implEval(RuntimeEnvironment *) const {
3290 return this->theBool;
3291 }
3292
implEval(RuntimeEnvironment *)3293 intrusive_ptr<Value> StringLiteral::implEval(RuntimeEnvironment *) const {
3294 return this->theString;
3295 }
3296
implEval(RuntimeEnvironment * runtimeEnv)3297 intrusive_ptr<Value> SumExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3298 return runtimeEnv->binaryOperatorDispatch(
3299 this->leftExp->evalAs<RightValue>(runtimeEnv),
3300 this->rightExp->evalAs<RightValue>(runtimeEnv),
3301 RuntimeEnvironment::opPlusMap,
3302 this->beginOperatorSourcePosition,
3303 this->endOperatorSourcePosition);
3304 }
3305
implEval(RuntimeEnvironment * runtimeEnv)3306 intrusive_ptr<Value> PowerExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3307 return runtimeEnv->binaryOperatorDispatch(
3308 this->leftExp->evalAs<RightValue>(runtimeEnv),
3309 this->rightExp->evalAs<RightValue>(runtimeEnv),
3310 RuntimeEnvironment::opPowerMap,
3311 this->beginOperatorSourcePosition,
3312 this->endOperatorSourcePosition);
3313 }
3314
implEval(RuntimeEnvironment * runtimeEnv)3315 intrusive_ptr<Value> IsInExpression::implEval(RuntimeEnvironment *runtimeEnv) const
3316 {
3317 intrusive_ptr<RightValue> v = this->leftExp->evalAs<RightValue>(runtimeEnv);
3318 intrusive_ptr<RightValue> container = this->rightExp->evalAs<RightValue>(runtimeEnv);
3319 // First case: sthg ISIN list
3320 if (const intrusive_ptr<LIST> list = dynamic_pointer_cast<LIST>(container))
3321 {
3322 LIST::ContainerType::size_type size = list->size();
3323 for(LIST::ContainerType::size_type a=0; a<size; ++a)
3324 {
3325 try
3326 {
3327 intrusive_ptr<BOOL> bv = intrusive_ptr_cast<BOOL>(
3328 runtimeEnv->binaryOperatorDispatch(
3329 v,
3330 list->getValue(a),
3331 RuntimeEnvironment::opEqualMap,
3332 this->getBegin(),
3333 this->getEnd()));
3334 if (bv->theBool)
3335 return bv;
3336 }
3337 catch (const InterruptException &) { throw; }
3338 catch (const RuntimeException &) { /* ignore errors from opEqual */ }
3339 }
3340 return BOOL::falseValue;
3341 }
3342 // Second case: substr ISIN string
3343 if (const intrusive_ptr<STRING> str = dynamic_pointer_cast<STRING>(container))
3344 {
3345 intrusive_ptr<STRING> leftStr = dynamic_pointer_cast<STRING>(v);
3346 if (!leftStr)
3347 throw WrongTypeException(STRING::type->name, v->getType()->name, this->leftExp);
3348 return Value::from(str->theString.find(leftStr->theString)!=string::npos);
3349 }
3350 // Third case: sthg ISIN ideal
3351 if (const intrusive_ptr<IDEAL> I = dynamic_pointer_cast<IDEAL>(container))
3352 {
3353 try
3354 {
3355 // Handle separately different types for sthg: RINGELEM, INT, RAT
3356 if (intrusive_ptr<RINGELEM> f = dynamic_pointer_cast<RINGELEM>(v))
3357 return Value::from(IsElem(f->theRingElem, I->theIdeal));
3358 if (intrusive_ptr<INT> f = dynamic_pointer_cast<INT>(v))
3359 return Value::from(IsElem(f->theBigInt, I->theIdeal));
3360 if (intrusive_ptr<RAT> f = dynamic_pointer_cast<RAT>(v))
3361 return Value::from(IsElem(f->theBigRat, I->theIdeal));
3362 }
3363 catch (const ErrorInfo& err) { throw RuntimeException(message_forC5(err), beginOperatorSourcePosition, endOperatorSourcePosition); }
3364 catch (const InterruptReceived& /*intr*/) { throw InterruptException(beginOperatorSourcePosition, endOperatorSourcePosition); }
3365
3366 throw WrongTypeException(RINGELEM::type->name + " or " +
3367 INT::type->name + " or " +
3368 RAT::type->name, v->getType()->name, this->leftExp);
3369 }
3370 // Fourth case: moduleelem ISIN module
3371 if (const intrusive_ptr<MODULE> M = dynamic_pointer_cast<MODULE>(container))
3372 {
3373 if (intrusive_ptr<MODULEELEM> mv = dynamic_pointer_cast<MODULEELEM>(v))
3374 try { return Value::from(IsElem(mv->theModuleElem, M->theModule)); }
3375 catch (const ErrorInfo& err) { throw RuntimeException(message_forC5(err), beginOperatorSourcePosition, endOperatorSourcePosition); }
3376 catch (const InterruptReceived& /*intr*/) { throw InterruptException(beginOperatorSourcePosition, endOperatorSourcePosition); }
3377 throw WrongTypeException(MODULEELEM::type->name,
3378 v->getType()->name, this->leftExp);
3379 }
3380 // Not a recognised container type, so give error
3381 throw WrongTypeException(
3382 LIST::type->name + " or " + STRING::type->name + " or " +
3383 IDEAL::type->name + " or " + MODULE::type->name,
3384 container->getType()->name,
3385 this->rightExp);
3386 }
3387
implEval(RuntimeEnvironment * runtimeEnv)3388 intrusive_ptr<Value> AndExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3389 intrusive_ptr<BOOL> left = this->leftExp->evalAs<BOOL>(runtimeEnv);
3390 if (!left->theBool)
3391 return left;
3392 return this->rightExp->evalAs<BOOL>(runtimeEnv);
3393 }
3394
implEval(RuntimeEnvironment * runtimeEnv)3395 intrusive_ptr<Value> OrExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3396 intrusive_ptr<BOOL> left = this->leftExp->evalAs<BOOL>(runtimeEnv);
3397 if (left->theBool)
3398 return left;
3399 return this->rightExp->evalAs<BOOL>(runtimeEnv);
3400 }
3401
implEval(RuntimeEnvironment * runtimeEnv)3402 intrusive_ptr<Value> LessThanExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3403 return runtimeEnv->binaryOperatorDispatch(
3404 this->leftExp->evalAs<RightValue>(runtimeEnv),
3405 this->rightExp->evalAs<RightValue>(runtimeEnv),
3406 RuntimeEnvironment::opLessThanMap,
3407 this->beginOperatorSourcePosition,
3408 this->endOperatorSourcePosition);
3409 }
3410
implEval(RuntimeEnvironment * runtimeEnv)3411 intrusive_ptr<Value> LessOrEqualExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3412 return runtimeEnv->binaryOperatorDispatch(
3413 this->leftExp->evalAs<RightValue>(runtimeEnv),
3414 this->rightExp->evalAs<RightValue>(runtimeEnv),
3415 RuntimeEnvironment::opLessOrEqualMap,
3416 this->beginOperatorSourcePosition,
3417 this->endOperatorSourcePosition);
3418 }
3419
implEval(RuntimeEnvironment * runtimeEnv)3420 intrusive_ptr<Value> EqualExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3421 return runtimeEnv->binaryOperatorDispatch(
3422 this->leftExp->evalAs<RightValue>(runtimeEnv),
3423 this->rightExp->evalAs<RightValue>(runtimeEnv),
3424 RuntimeEnvironment::opEqualMap,
3425 this->beginOperatorSourcePosition,
3426 this->endOperatorSourcePosition);
3427 }
3428
implEval(RuntimeEnvironment * runtimeEnv)3429 intrusive_ptr<Value> NotEqualExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3430 return runtimeEnv->binaryOperatorDispatch(
3431 this->leftExp->evalAs<RightValue>(runtimeEnv),
3432 this->rightExp->evalAs<RightValue>(runtimeEnv),
3433 RuntimeEnvironment::opNotEqualMap,
3434 this->beginOperatorSourcePosition,
3435 this->endOperatorSourcePosition);
3436 }
3437
implEval(RuntimeEnvironment * runtimeEnv)3438 intrusive_ptr<Value> GreaterOrEqualExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3439 return runtimeEnv->binaryOperatorDispatch(
3440 this->leftExp->evalAs<RightValue>(runtimeEnv),
3441 this->rightExp->evalAs<RightValue>(runtimeEnv),
3442 RuntimeEnvironment::opGreaterOrEqualMap,
3443 this->beginOperatorSourcePosition,
3444 this->endOperatorSourcePosition);
3445 }
3446
implEval(RuntimeEnvironment * runtimeEnv)3447 intrusive_ptr<Value> GreaterThanExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3448 return runtimeEnv->binaryOperatorDispatch(
3449 this->leftExp->evalAs<RightValue>(runtimeEnv),
3450 this->rightExp->evalAs<RightValue>(runtimeEnv),
3451 RuntimeEnvironment::opGreaterThanMap,
3452 this->beginOperatorSourcePosition,
3453 this->endOperatorSourcePosition);
3454 }
3455
implEval(RuntimeEnvironment * runtimeEnv)3456 intrusive_ptr<Value> SubtractionExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3457 return runtimeEnv->binaryOperatorDispatch(
3458 this->leftExp->evalAs<RightValue>(runtimeEnv),
3459 this->rightExp->evalAs<RightValue>(runtimeEnv),
3460 RuntimeEnvironment::opMinusMap,
3461 this->beginOperatorSourcePosition,
3462 this->endOperatorSourcePosition);
3463 }
3464
implEval(RuntimeEnvironment * runtimeEnv)3465 intrusive_ptr<Value> ProductExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3466 return runtimeEnv->binaryOperatorDispatch(
3467 this->leftExp->evalAs<RightValue>(runtimeEnv),
3468 this->rightExp->evalAs<RightValue>(runtimeEnv),
3469 RuntimeEnvironment::opStarMap,
3470 this->beginOperatorSourcePosition,
3471 this->endOperatorSourcePosition);
3472 }
3473
implEval(RuntimeEnvironment * runtimeEnv)3474 intrusive_ptr<Value> DivisionExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3475 return runtimeEnv->binaryOperatorDispatch(
3476 this->leftExp->evalAs<RightValue>(runtimeEnv),
3477 this->rightExp->evalAs<RightValue>(runtimeEnv),
3478 RuntimeEnvironment::opSlashMap,
3479 this->beginOperatorSourcePosition,
3480 this->endOperatorSourcePosition);
3481 }
3482
implEval(RuntimeEnvironment * runtimeEnv)3483 intrusive_ptr<Value> SummationExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3484 vector<Token>::const_iterator opIt = this->operators.begin();
3485 vector<intrusive_ptr<Expression> >::const_iterator expIt = this->operands.begin();
3486 vector<intrusive_ptr<Expression> >::const_iterator expEnd = this->operands.end();
3487 assert(expIt!=expEnd);
3488 intrusive_ptr<RightValue> currValue = (*expIt++)->evalAs<RightValue>(runtimeEnv);
3489 while (expIt!=expEnd) {
3490 assert(opIt!=operators.end());
3491 const Token op = *opIt++;
3492 const TokenType tt = op.getType();
3493 assert(tt==TT_PLUS || tt==TT_MINUS);
3494 currValue = runtimeEnv->binaryOperatorDispatch(
3495 currValue,
3496 (*expIt++)->evalAs<RightValue>(runtimeEnv),
3497 tt == TT_PLUS ? RuntimeEnvironment::opPlusMap : RuntimeEnvironment::opMinusMap,
3498 op.getBegin(),
3499 op.getEnd());
3500 }
3501 return currValue;
3502 }
3503
implEval(RuntimeEnvironment * runtimeEnv)3504 intrusive_ptr<Value> MultiplicationExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3505 vector<Token>::const_iterator opIt = this->operators.begin();
3506 vector<intrusive_ptr<Expression> >::const_iterator expIt = this->operands.begin();
3507 vector<intrusive_ptr<Expression> >::const_iterator expEnd = this->operands.end();
3508 assert(expIt!=expEnd);
3509 intrusive_ptr<RightValue> currValue = (*expIt++)->evalAs<RightValue>(runtimeEnv);
3510 while (expIt!=expEnd) {
3511 assert(opIt!=operators.end());
3512 const Token op = *opIt++;
3513 RuntimeEnvironment::DispatchMapType *map;
3514 switch(op.getType()) {
3515 case TT_STAR:
3516 map = &RuntimeEnvironment::opStarMap;
3517 break;
3518 case TT_SLASH:
3519 map = &RuntimeEnvironment::opSlashMap;
3520 break;
3521 case TT_MOD:
3522 map = &RuntimeEnvironment::opModMap;
3523 break;
3524 case TT_COLON:
3525 map = &RuntimeEnvironment::opColonMap;
3526 break;
3527 default:
3528 assert(false);
3529 throw RuntimeException("Something rather unpleasant has happened (op.getType() returned an unknown value) and I'm way too confused to continue", op.getBegin(), op.getEnd());
3530 }
3531 currValue = runtimeEnv->binaryOperatorDispatch(currValue, (*expIt++)->evalAs<RightValue>(runtimeEnv), *map, op.getBegin(), op.getEnd());
3532 }
3533 return currValue;
3534 }
3535
tryToFindFrame(RuntimeEnvironment * runtimeEnv)3536 Frame *StaticEnv::VarData::tryToFindFrame(RuntimeEnvironment *runtimeEnv) const {
3537 assert(this->depth>StaticEnv::IN_THE_WILD);
3538 Frame *f;
3539 if (this->depth==StaticEnv::TOP_LEVEL) {
3540 #ifdef VERBOSE_RUNTIME_DEBUG
3541 cout << "StaticEnv::VarData::tryToFindFrame f = toplevel\n";
3542 #endif // #ifdef VERBOSE_RUNTIME_DEBUG
3543 f = runtimeEnv->getTopLevelFrame();
3544 assert(f);
3545 } else {
3546 f = runtimeEnv->getCurrentFrame();
3547 assert(f);
3548 #ifdef VERBOSE_RUNTIME_DEBUG
3549 cout << "StaticEnv::VarData::tryToFindFrame f=" << f << ", depth=" << this->depth << endl;
3550 #endif // #ifdef VERBOSE_RUNTIME_DEBUG
3551 for(int a=0; a<this->depth; ++a) {
3552 #ifdef VERBOSE_RUNTIME_DEBUG
3553 cout << "StaticEnv::VarData::tryToFindFrame a=" << a << ", f=";
3554 #endif // #ifdef VERBOSE_RUNTIME_DEBUG
3555 f = f->accessLink.toCheckedPointer();
3556 #ifdef VERBOSE_RUNTIME_DEBUG
3557 cout << "StaticEnv::VarData::tryToFindFrame final f=" << f << endl;
3558 #endif // #ifdef VERBOSE_RUNTIME_DEBUG
3559 if (!f)
3560 break;
3561 }
3562 }
3563 return f;
3564 }
3565
3566 #ifdef C5IDE
debuggerTryToFindFrame(const Frame * topLevelFrame,const Frame * currentFrame)3567 const Frame *StaticEnv::VarData::debuggerTryToFindFrame(const Frame *topLevelFrame, const Frame *currentFrame) const {
3568 assert(this->depth>StaticEnv::IN_THE_WILD);
3569 const Frame *f;
3570 if (this->depth==StaticEnv::TOP_LEVEL) {
3571 f = topLevelFrame;
3572 assert(f);
3573 } else {
3574 f = currentFrame;
3575 assert(f);
3576 for(int a=0; a<this->depth; ++a) {
3577 f = f->accessLink.toCheckedPointer();
3578 if (!f)
3579 break;
3580 }
3581 }
3582 return f;
3583 }
3584 #endif // #ifdef C5IDE
3585
implEval(RuntimeEnvironment * runtimeEnv)3586 intrusive_ptr<Value> Identifier::implEval(RuntimeEnvironment *runtimeEnv) const {
3587 #ifdef VERBOSE_RUNTIME_DEBUG
3588 cout << "Identifier::eval Finding frame for " << this->identifier << endl;
3589 #endif // #ifdef VERBOSE_RUNTIME_DEBUG
3590 Frame * const f = this->varData.tryToFindFrame(runtimeEnv);
3591 if (!f)
3592 throw DeadEnviromentException(this);
3593 if (this->varData.isCapturedValue) {
3594 assert(f->userdefinedFun);
3595 assert(static_cast<vector<intrusive_ptr<RightValue> >::size_type>(this->varData.index) < f->userdefinedFun->capturedValues.size());
3596 const intrusive_ptr<Value> v(f->userdefinedFun->capturedValues[this->varData.index]);
3597 #ifdef VERBOSE_RUNTIME_DEBUG
3598 cout << "Identifier::eval: it's the captured value v=" << v << endl;
3599 #endif // #ifdef VERBOSE_RUNTIME_DEBUG
3600 return v;
3601 }
3602 const int index = this->varData.index;
3603 #ifdef VERBOSE_RUNTIME_DEBUG
3604 cout << "Identifier::eval index=" << index << endl;
3605 #endif // #ifdef VERBOSE_RUNTIME_DEBUG
3606 if (index>=0) {
3607 const intrusive_ptr<Value> v = f->varSlots[index].value;
3608 #ifdef VERBOSE_RUNTIME_DEBUG
3609 cout << "Identifier::eval v=" << v << endl;
3610 #endif // #ifdef VERBOSE_RUNTIME_DEBUG
3611 if (dynamic_pointer_cast<LeftValue>(v)) {
3612 #ifdef VERBOSE_RUNTIME_DEBUG
3613 cout << "Identifier::eval returning a ReferenceVariable\n";
3614 #endif // #ifdef VERBOSE_RUNTIME_DEBUG
3615 return new ReferenceVariable(this, f, index);
3616 }
3617 }
3618 #ifdef VERBOSE_RUNTIME_DEBUG
3619 cout << "Identifier::eval returning a VariableName\n";
3620 #endif // #ifdef VERBOSE_RUNTIME_DEBUG
3621 return new VariableName(runtimeEnv, f, index, this);
3622 }
3623
implEval(RuntimeEnvironment * runtimeEnv)3624 intrusive_ptr<Value> IsDefinedExp::implEval(RuntimeEnvironment *runtimeEnv) const {
3625 if (this->expId->varData.isCapturedValue) {
3626 runtimeEnv->interpreter->reportWarning("This expression will be always true, since imported values are always defined", this);
3627 return BOOL::trueValue;
3628 }
3629 VariableSlot *vs;
3630 try {
3631 vs = this->expId->getVariableSlot(runtimeEnv);
3632 //JAA vs->asRightValue(); // throws if not defined; otherwise ignore result
3633 } catch (VariableNotFoundException &) {
3634 return BOOL::falseValue;
3635 }
3636 //JAA catch (const RunTimeException&)
3637 //JAA { return BOOL::falseValue; }
3638 assert(vs->value); // getVariableSlot should throw an exception if vs->value==0 (this might happen when a package is reloaded or an indeterminate removed)
3639 if (dynamic_pointer_cast<VoidValue>(vs->value)) // void means optional-arg without value
3640 return BOOL::falseValue;
3641 if (const intrusive_ptr<LeftValue> lv = dynamic_pointer_cast<LeftValue>(vs->value))
3642 try {
3643 lv->asRightValue();
3644 } catch (const InterruptException &) {
3645 throw;
3646 } catch (const RuntimeException &) {
3647 return BOOL::falseValue;
3648 }
3649 return BOOL::trueValue;
3650 }
3651
implEval(RuntimeEnvironment * runtimeEnv)3652 intrusive_ptr<Value> FieldAccessExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3653 intrusive_ptr<Value> v = this->targetExp->eval(runtimeEnv);
3654 if (const intrusive_ptr<LeftValue> lv = dynamic_pointer_cast<LeftValue>(v)) {
3655 if (const intrusive_ptr<VariableName> vn = dynamic_pointer_cast<VariableName>(lv))
3656 if (vn->expId->identifier[0]=='$') {
3657 intrusive_ptr<PackageValue> pv = intrusive_ptr_cast<PackageValue>(vn->asRightValue());
3658 return pv->toVariableName(runtimeEnv, this->name, this->tokName);
3659 }
3660 return new FieldAccess(lv, this->name, intrusive_ptr<const FieldAccessExpression>(this));
3661 }
3662 intrusive_ptr<RECORD> rv = dynamic_pointer_cast<RECORD>(v);
3663 if (!rv)
3664 throw WrongTypeException(
3665 RECORD::type->name+" or "+PackageValue::type->name,
3666 intrusive_ptr_cast<RightValue>(v)->getType()->name,
3667 this->targetExp->getBegin(),
3668 this->targetExp->getEnd());
3669 intrusive_ptr<RightValue> fieldValue = rv->getField(this->name, this->tokName.getBegin(), this->tokName.getEnd());
3670 if (!fieldValue)
3671 throw FieldNotFoundException(this->name, this->tokName.getBegin(), this->tokName.getEnd(), rv);
3672 return fieldValue;
3673 }
3674
implEval(RuntimeEnvironment * runtimeEnv)3675 intrusive_ptr<Value> IndexedAccessExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3676 intrusive_ptr<Value> v = this->targetExp->eval(runtimeEnv);
3677 const CharPointer targetExpBegin = this->targetExp->getBegin();
3678 CharPointer targetExpEnd = this->targetExp->getEnd();
3679 typedef intrusive_ptr<Expression> expPtr;
3680 BOOST_FOREACH(expPtr indexExp, this->indexes) {
3681 const intrusive_ptr<RightValue> indexValue = indexExp->evalAs<RightValue>(runtimeEnv);
3682 const CharPointer indexExpBegin = indexExp->getBegin();
3683 const CharPointer indexExpEnd = indexExp->getEnd();
3684 if (intrusive_ptr<INT> N = dynamic_pointer_cast<INT>(indexValue))
3685 v = v->indexedByBigInt(N, targetExpBegin, targetExpEnd, indexExpBegin, indexExpEnd);
3686 else if (intrusive_ptr<STRING> str = dynamic_pointer_cast<STRING>(indexValue))
3687 v = v->indexedByString(str, targetExpBegin, targetExpEnd, indexExpBegin, indexExpEnd);
3688 else
3689 throw WrongTypeException(INT::type->name + " or " + STRING::type->name, indexValue->getType()->name, indexExpBegin, indexExpEnd);
3690 targetExpEnd = indexExpEnd;
3691 }
3692 return v;
3693 }
3694
implEval(RuntimeEnvironment * runtimeEnv)3695 intrusive_ptr<Value> RecordExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3696 intrusive_ptr<RECORD> r(new RECORD());
3697 BOOST_FOREACH(const RecordField &rf, this->fields) {
3698 intrusive_ptr<const Identifier> idExp = intrusive_ptr_cast<const Identifier>(rf.name);
3699 RECORD::CheckFieldName(idExp->identifier, idExp);
3700 if (r->getFieldNoCheck(idExp->identifier))
3701 throw RuntimeException("Duplicate field", idExp);
3702 r->setFieldNoCheck(idExp->identifier, rf.initExp->evalAs<RightValue>(runtimeEnv));
3703 }
3704 return r;
3705 }
3706
implEval(RuntimeEnvironment * runtimeEnv)3707 intrusive_ptr<Value> ListExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3708 intrusive_ptr<LIST> l(new LIST());
3709 BOOST_FOREACH(intrusive_ptr<const Expression> e, this->exps) {
3710 l->addValue(e->evalAs<RightValue>(runtimeEnv));
3711 }
3712 return l;
3713 }
3714
implEval(RuntimeEnvironment * runtimeEnv)3715 intrusive_ptr<Value> CartesianProductExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3716 intrusive_ptr<LIST> previous(new LIST());
3717 previous->addValue(new LIST(this->operands.size()));
3718 intrusive_ptr<LIST> current;
3719 BOOST_FOREACH(intrusive_ptr<const Expression> e, this->operands) {
3720 intrusive_ptr<LIST> l = e->evalAs<LIST>(runtimeEnv);
3721 const LIST::ContainerType::size_type lSize = l->size();
3722 const LIST::ContainerType::size_type previousSize = previous->size();
3723 current = new LIST();
3724 for(LIST::ContainerType::size_type a=0; a<previousSize; ++a) {
3725 for(LIST::ContainerType::size_type b=0; b<lSize; ++b) {
3726 intrusive_ptr<LIST> cloned = intrusive_ptr_cast<LIST>(previous->getValue(a)->clone());
3727 cloned->addValue(l->getValue(b));
3728 current->addValue(cloned);
3729 }
3730 }
3731 previous = current;
3732 }
3733 return current;
3734 }
3735
implEval(RuntimeEnvironment * runtimeEnv)3736 intrusive_ptr<Value> ExpSuchThatIdInExpAndExp::implEval(RuntimeEnvironment *runtimeEnv) const {
3737 intrusive_ptr<LIST> list = this->exp2->evalAs<LIST>(runtimeEnv);
3738 intrusive_ptr<LIST> result(new LIST());
3739 Frame *f = runtimeEnv->pushIterationFrame(this);
3740 BOOST_SCOPE_EXIT( (runtimeEnv) ) {
3741 runtimeEnv->popFrame();
3742 } BOOST_SCOPE_EXIT_END
3743 VariableSlot &varSlot = f->varSlots.front();
3744 const int size = list->size();
3745 for(int a=0; a<size; ++a) {
3746 intrusive_ptr<RightValue> sourceElem = list->getValue(a);
3747 assert(sourceElem);
3748 varSlot.value = sourceElem;
3749 if (!this->optionalExp3 || this->optionalExp3->evalAs<BOOL>(runtimeEnv)->theBool)
3750 result->addValue(this->exp1->evalAs<RightValue>(runtimeEnv));
3751 }
3752 return result;
3753 }
3754
implEval(RuntimeEnvironment * runtimeEnv)3755 intrusive_ptr<Value> IdInExpSuchThatExp::implEval(RuntimeEnvironment *runtimeEnv) const {
3756 intrusive_ptr<LIST> list = this->exp1->evalAs<LIST>(runtimeEnv);
3757 Frame *f = runtimeEnv->pushIterationFrame(this);
3758 BOOST_SCOPE_EXIT( (runtimeEnv) ) {
3759 runtimeEnv->popFrame();
3760 } BOOST_SCOPE_EXIT_END
3761 VariableSlot &varSlot = f->varSlots.front();
3762 intrusive_ptr<LIST> result(new LIST());
3763 const int size = list->size();
3764 for(int a=0; a<size; ++a) {
3765 intrusive_ptr<RightValue> elem = list->getValue(a);
3766 assert(elem);
3767 varSlot.value = elem;
3768 if (this->exp2->evalAs<BOOL>(runtimeEnv)->theBool)
3769 result->addValue(elem);
3770 }
3771 return result;
3772 }
3773
implEval(RuntimeEnvironment * runtimeEnv)3774 intrusive_ptr<Value> DotDotExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3775 const intrusive_ptr<LIST> l(new LIST());
3776 const intrusive_ptr<RightValue>
3777 lo = this->leftExp->evalAs<RightValue>(runtimeEnv),
3778 hi = this->rightExp->evalAs<RightValue>(runtimeEnv);
3779 std::string ErrMesg = "range operator \"dot-dot\": only between INTs or between indets of the same ring";
3780 intrusive_ptr<INT> NL, NR;
3781 intrusive_ptr<RINGELEM> xL, xR;
3782 if ((NL=dynamic_pointer_cast<INT>(lo)) && (NR=dynamic_pointer_cast<INT>(hi)))
3783 {
3784 BigInt lower(NL->theBigInt), upper(NR->theBigInt);
3785 if (upper-lower > 10000000) // BUG??? arbitrary max size
3786 throw RuntimeException("dot-dot range limited to 10000000 values",this);
3787 for(; lower<=upper; ++lower) l->addValue(new INT(lower));
3788 }
3789 else
3790 if ((xL=dynamic_pointer_cast<RINGELEM>(lo)) && (xR=dynamic_pointer_cast<RINGELEM>(hi)))
3791 {
3792 const ring theRing(owner(xL->theRingElem));
3793 if (theRing!=owner(xR->theRingElem)) throw RuntimeException(ErrMesg,this);
3794 if (!IsPolyRing(theRing)) throw RuntimeException(ErrMesg, this);
3795 const PolyRing polyRing = theRing;
3796 long lower, upper;
3797 if (!IsIndet(lower,xL->theRingElem)) throw RuntimeException(ErrMesg,this->leftExp);
3798 if (!IsIndet(upper,xR->theRingElem)) throw RuntimeException(ErrMesg,this->rightExp);
3799 for(; lower<=upper; ++lower)
3800 l->addValue(new RINGELEM(indet(polyRing, lower)));
3801 }
3802 else
3803 throw RuntimeException(ErrMesg, this);
3804 return l;
3805 }
3806
3807
implEval(RuntimeEnvironment * runtimeEnv)3808 intrusive_ptr<Value> InvocationExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
3809 intrusive_ptr<RightValue> target = this->targetExp->evalAs<RightValue>(runtimeEnv);
3810 intrusive_ptr<FUNCTION> fun = dynamic_pointer_cast<FUNCTION>(target);
3811 if (!fun)
3812 throw WrongTypeException(FUNCTION::type->name,
3813 target->getType()->name + " (maybe you forgot \"*\"?)",
3814 this->targetExp);
3815 return fun->eval(this, runtimeEnv);
3816 }
3817
3818
3819 namespace {
dontKnow(const intrusive_ptr<const Statement> s)3820 intrusive_ptr<Value> dontKnow(const intrusive_ptr<const Statement> s) {
3821 throw RuntimeException("I don't know (yet) how to execute this statement", s->getBegin(), s->getEnd());
3822 }
3823 }
3824
implExecute(RuntimeEnvironment * runtimeEnv)3825 void UseStatement::implExecute(RuntimeEnvironment *runtimeEnv) {
3826 const intrusive_ptr<RING> ring = this->ringDefinition->eval(runtimeEnv);
3827 string ringName;
3828 if (this->identifier) {
3829 ringName = this->identifier->identifier;
3830 const intrusive_ptr<LeftValue> leftValue = this->identifier->evalAs<LeftValue>(runtimeEnv);
3831 if (leftValue->assignmentNeedsOwnership())
3832 leftValue->obtainOwnership();
3833 leftValue->assign(ring, this->ringDefinition->getBegin(), this->ringDefinition->getEnd(), runtimeEnv);
3834 }
3835 if (runtimeEnv->currentRing)
3836 runtimeEnv->currentRing->removeInjectedIndeterminates(runtimeEnv);
3837 runtimeEnv->currentRing = ring;
3838 runtimeEnv->getTopLevelFrame()->varSlots[runtimeEnv->currentRingSlot].value = ring;
3839 ring->injectIndeterminates(runtimeEnv, this->ringDefinition, ringName);
3840 }
3841
implExecute(RuntimeEnvironment *)3842 void UsingStatement::implExecute(RuntimeEnvironment *) {
3843 dontKnow(this);
3844 }
3845
implExecute(RuntimeEnvironment * runtimeEnv)3846 void DescribeStatement::implExecute(RuntimeEnvironment *runtimeEnv) {
3847 this->exp->evalAs<RightValue>(runtimeEnv)->describe(runtimeEnv->getOutputStream());
3848 }
3849
implExecute(RuntimeEnvironment * runtimeEnv)3850 void HelpStatement::implExecute(RuntimeEnvironment *runtimeEnv) {
3851 try {
3852 ostringstream os;
3853 OnlineHelp::PrintMan(os, this->topic);
3854 runtimeEnv->getOutputStream()->print(os.str())->flush();
3855 } catch (const std::exception& err) {
3856 throw RuntimeException(err.what(), this);
3857 }
3858 }
3859
eval(InterpreterNS::RuntimeEnvironment * runtimeEnv)3860 intrusive_ptr<RING> RingDefinition::eval(InterpreterNS::RuntimeEnvironment *runtimeEnv) const {
3861 try {
3862 intrusive_ptr<RING> ring = this->identifier->evalAs<RING>(runtimeEnv);
3863 if (this->optionalExp) {
3864 const intrusive_ptr<RightValue> quotient = this->optionalExp->evalAs<RightValue>(runtimeEnv);
3865 if (const intrusive_ptr<INT> N = dynamic_pointer_cast<INT>(quotient))
3866 ring = new RING(NewQuotientRing(ring->theRing, ideal(RingElem(ring->theRing, N->theBigInt))));
3867 else if (const intrusive_ptr<RINGELEM> poly = dynamic_pointer_cast<RINGELEM>(quotient))
3868 ring = new RING(NewQuotientRing(ring->theRing, ideal(poly->theRingElem)));
3869 else if (const intrusive_ptr<IDEAL> ideal = dynamic_pointer_cast<IDEAL>(quotient))
3870 ring = new RING(NewQuotientRing(ring->theRing, ideal->theIdeal));
3871 else
3872 throw WrongTypeException(INT::type->name + ", " + RINGELEM::type->name + " or " + IDEAL::type->name, quotient->getType()->name, this->optionalExp);
3873 }
3874 if (!this->indeterminates.empty()) {
3875 vector<symbol> symbols;
3876 BOOST_FOREACH(intrusive_ptr<IndeterminateDeclaration> ind, this->indeterminates) {
3877 if (ind->ranges.empty()) {
3878 symbols.push_back(symbol(ind->identifier->identifier));
3879 continue;
3880 }
3881 vector<pair<long, long> > ranges;
3882 typedef pair<intrusive_ptr<Expression>, intrusive_ptr<Expression> > ExpPair;
3883 BOOST_FOREACH(const ExpPair &p, ind->ranges) {
3884 intrusive_ptr<INT> lower = p.first->evalAs<INT>(runtimeEnv);
3885 long l1;
3886 if (!IsConvertible(l1, lower->theBigInt))
3887 throw RuntimeException("The index does not fit a machine-integer", p.first);
3888 intrusive_ptr<INT> upper = p.second ? p.second->evalAs<INT>(runtimeEnv) : lower;
3889 long l2;
3890 if (!IsConvertible(l2, upper->theBigInt))
3891 throw RuntimeException("The index does not fit a machine-integer", p.second);
3892 if (l2<l1)
3893 throw RuntimeException("The upper bound is smaller than the lower bound", p.first->getBegin(), p.second->getEnd());
3894 ranges.push_back(make_pair(l1, l2));
3895 }
3896 vector<long> indexes;
3897 for(vector<pair<long, long> >::size_type a=0; a<ranges.size(); ++a)
3898 indexes.push_back(ranges[a].first);
3899 for(;;) {
3900 symbols.push_back(symbol(ind->identifier->identifier, indexes));
3901 int incIndex = indexes.size()-1;
3902 while (incIndex>=0)
3903 if ( ++indexes[incIndex]>ranges[incIndex].second ) {
3904 indexes[incIndex] = ranges[incIndex].first;
3905 --incIndex;
3906 } else
3907 break;
3908 if (incIndex==-1)
3909 break;
3910 }
3911 }
3912 /*ostringstream os;
3913 BOOST_FOREACH(const symbol &s, symbols)
3914 os << ' ' << s;
3915 runtimeEnv->getOutputStream()->print("Symbols:")->println(os.str());*/
3916 switch (this->maybeOrderTT) {
3917 case TT_LEX:
3918 ring = new RING(NewPolyRing(ring->theRing, symbols, lex));
3919 break;
3920 case TT_DEGLEX:
3921 ring = new RING(NewPolyRing(ring->theRing, symbols, StdDegLex));
3922 break;
3923 case TT_DEGREVLEX:
3924 ring = new RING(NewPolyRing(ring->theRing, symbols, StdDegRevLex));
3925 break;
3926 default:
3927 ring = new RING(NewPolyRing(ring->theRing, symbols));
3928 }
3929 }
3930 return ring;
3931 }
3932 catch (const ErrorInfo& err)
3933 {
3934 runtimeEnv->announceCLE(err);
3935 throw RuntimeException(message_forC5(err), this);
3936 }
3937 catch (const InterruptReceived& /*intr*/)
3938 {
3939 throw InterruptException(this);
3940 }
3941 }
3942
implExecute(RuntimeEnvironment * runtimeEnv)3943 void RingAssignStatement::implExecute(RuntimeEnvironment *runtimeEnv) {
3944 const intrusive_ptr<LeftValue> leftValue = this->leftExp->evalAs<LeftValue>(runtimeEnv);
3945 runtimeEnv->interpreter->checkForInterrupts(this->leftExp);
3946 const intrusive_ptr<RING> ring = this->ringDef->eval(runtimeEnv);
3947 if (leftValue->assignmentNeedsOwnership())
3948 leftValue->obtainOwnership();
3949 leftValue->assign(ring, this->ringDef->getBegin(), this->ringDef->getEnd(), runtimeEnv);
3950 }
3951
implExecute(RuntimeEnvironment *)3952 void TimeStatement::implExecute(RuntimeEnvironment *) {
3953 dontKnow(this);
3954 }
3955
implExecute(RuntimeEnvironment *)3956 void EmptyStatement::implExecute(RuntimeEnvironment *) {
3957 // nothing to do here, what a lovely statement ;-)
3958 }
3959
implExecute(RuntimeEnvironment *)3960 void SkipStatement::implExecute(RuntimeEnvironment *) {
3961 // nothing to do here, what a lovely statement ;-)
3962 }
3963
getVariableSlot(RuntimeEnvironment * runtimeEnv)3964 VariableSlot *Identifier::getVariableSlot(RuntimeEnvironment *runtimeEnv) {
3965 Frame * const f = this->varData.tryToFindFrame(runtimeEnv);
3966 if (!f)
3967 throw DeadEnviromentException(this);
3968 int index = this->varData.index;
3969 if (index<0) {
3970 assert(f==runtimeEnv->getTopLevelFrame());
3971 index = runtimeEnv->slotFor(this->identifier);
3972 if (index<0)
3973 throw VariableNotFoundException(this, runtimeEnv);
3974 this->varData.index = index;
3975 }
3976 VariableSlot &vs = f->varSlots[index];
3977 if (!vs.value) { // this can only happen when a package has been reloaded (and some of the previous version members are not defined anymore) or an indeterminate has been removed (by Use-ing another ring)
3978 assert(f==runtimeEnv->getTopLevelFrame());
3979 throw VariableNotFoundException(this, runtimeEnv);
3980 }
3981 return &vs;
3982 }
3983
implExecute(RuntimeEnvironment * runtimeEnv)3984 void ProtectStatement::implExecute(RuntimeEnvironment *runtimeEnv) {
3985 if (this->expId->varData.isCapturedValue)
3986 throw RuntimeException("Cannot protect a(n imported) value", this->expId);
3987 VariableSlot *vs = this->expId->getVariableSlot(runtimeEnv);
3988 if (vs->isSystemProtected())
3989 throw RuntimeException("This variable is already system-protected", this->expId);
3990 if (vs->isProtected())
3991 {
3992 string reason;
3993 if (!vs->getProtectionReason().empty())
3994 reason = " ("+vs->getProtectionReason()+")";
3995 throw RuntimeException("Variable already protected"+reason, this->expId);
3996 }
3997 string reason;
3998 if (this->optExp)
3999 reason = this->optExp->evalAs<STRING>(runtimeEnv)->theString;
4000 vs->protect(reason);
4001 }
4002
implExecute(RuntimeEnvironment * runtimeEnv)4003 void UnprotectStatement::implExecute(RuntimeEnvironment *runtimeEnv) {
4004 if (this->expId->varData.isCapturedValue)
4005 throw RuntimeException("Cannot unprotect a(n imported) value", this->expId);
4006 VariableSlot *vs = this->expId->getVariableSlot(runtimeEnv);
4007 if (vs->isSystemProtected())
4008 throw RuntimeException("Cannot unprotect a system-protected variable", this->expId);
4009 if (vs->isPackage())
4010 throw RuntimeException("Cannot unprotect a package-exported variable", this->expId);
4011 if (!vs->isProtected())
4012 runtimeEnv->interpreter->reportWarning("This variable was not protected", this->expId);
4013 vs->unprotect();
4014 }
4015
implExecute(RuntimeEnvironment * runtimeEnv)4016 void IfStatement::implExecute(RuntimeEnvironment *runtimeEnv) {
4017 BOOST_FOREACH(const IfBranch &branch, this->branches)
4018 if (!branch.optExp || branch.optExp->evalAs<BOOL>(runtimeEnv)->theBool) {
4019 branch.statements->execute(runtimeEnv);
4020 return;
4021 }
4022 }
4023
implExecute(RuntimeEnvironment * runtimeEnv)4024 void CiaoOrQuitStatement::implExecute(RuntimeEnvironment *runtimeEnv) {
4025 runtimeEnv->getOutputStream()->println("Ciao!");
4026 throw Ciao();
4027 }
4028
implExecute(RuntimeEnvironment * runtimeEnv)4029 void SourceStatement::implExecute(RuntimeEnvironment *runtimeEnv) {
4030 const string filename = this->exp->evalAs<STRING>(runtimeEnv)->theString;
4031 try {
4032 runtimeEnv->interpreter->readAndExecute(filename, false, this->ttype!=TT_LOAD);
4033 } catch (const RuntimeException &) {
4034 throw;
4035 } catch (const BaseException &be) {
4036 throw RuntimeException(be.reason, this->getBegin(), this->getEnd());
4037 }
4038 }
4039
implExecute(RuntimeEnvironment * runtimeEnv)4040 void SourceRegionStatement::implExecute(RuntimeEnvironment *runtimeEnv) {
4041 try
4042 {
4043 const long FromLine = ConvertTo<long>(this->expFromLine->evalAs<INT>(runtimeEnv)->theBigInt);
4044 const long FromChar = ConvertTo<long>(this->expFromChar->evalAs<INT>(runtimeEnv)->theBigInt);
4045 const long ToLine = ConvertTo<long>(this->expToLine->evalAs<INT>(runtimeEnv)->theBigInt);
4046 const long ToChar = ConvertTo<long>(this->expToChar->evalAs<INT>(runtimeEnv)->theBigInt);
4047
4048 const string filename = this->expFileName->evalAs<STRING>(runtimeEnv)->theString;
4049
4050 runtimeEnv->interpreter->readAndExecute(filename, false, true, FromLine,FromChar, ToLine,ToChar);
4051 }
4052 catch (const RuntimeException &)
4053 {
4054 throw;
4055 }
4056 catch (const BaseException &be)
4057 {
4058 throw RuntimeException(be.reason, this->getBegin(), this->getEnd());
4059 }
4060 catch (const CoCoA::ErrorInfo& err)
4061 {
4062 // Get here only if line no or char posn are outside range of long integer.
4063 throw RuntimeException("Line number or char position too large or negative", this->getBegin(), this->getEnd());
4064 }
4065 catch (const InterruptReceived& /*intr*/)
4066 {
4067 throw InterruptException(this->getBegin(), this->getEnd());
4068 }
4069 }
4070
implExecute(RuntimeEnvironment * runtimeEnv)4071 void EvalStatement::implExecute(RuntimeEnvironment *runtimeEnv) {
4072 intrusive_ptr<RightValue> v = this->exp->evalAsRightValueVoidIsOk(runtimeEnv);
4073 assert(v);
4074 if (!dynamic_pointer_cast<VoidValue>(v)) {
4075 Frame *currentFrame = runtimeEnv->getCurrentFrame();
4076 if (currentFrame->invocationExp)
4077 throw RuntimeException("Ignored value inside fn-proc! All values must be assigned"
4078 " or operated upon by a command/procedure (maybe you forgot to assign, print, or return it?)", this->getBegin(), this->getEnd());
4079 else
4080 runtimeEnv->getTopLevelFrame()->varSlots[runtimeEnv->itSlot].value = v;
4081 const intrusive_ptr<OSTREAM> output(runtimeEnv->getOutputStream());
4082 output->print(runtimeEnv, v, this->exp);
4083 output->newline();
4084 #ifdef PRINT_REFCOUNTS
4085 output->print(v->refCountAsString());
4086 #endif // #ifdef PRINT_REFCOUNTS
4087 }
4088 }
4089
implExecute(RuntimeEnvironment * runtimeEnv)4090 void PrintStatement::implExecute(RuntimeEnvironment *runtimeEnv) {
4091 intrusive_ptr<OSTREAM> out = this->onExp ?
4092 this->onExp->evalAs<OSTREAM>(runtimeEnv) :
4093 runtimeEnv->getOutputStream();
4094 BOOST_FOREACH(intrusive_ptr<const Expression> e, this->exps) {
4095 intrusive_ptr<RightValue> v = e->evalAs<RightValue>(runtimeEnv);
4096 out->print(runtimeEnv, v, e);
4097 }
4098 if (this->ttype==TT_PRINTLN)
4099 out->newline();
4100 out->flush();
4101 }
4102
implExecute(RuntimeEnvironment * runtimeEnv)4103 void ForStatement::implExecute(RuntimeEnvironment *runtimeEnv) {
4104 BigInt begin(this->beginExp->evalAs<INT>(runtimeEnv)->theBigInt);
4105 BigInt end(this->endExp->evalAs<INT>(runtimeEnv)->theBigInt);
4106 BigInt step(1);
4107 if (this->stepExp) {
4108 step = this->stepExp->evalAs<INT>(runtimeEnv)->theBigInt;
4109 if (IsZero(step))
4110 throw RuntimeException("Step value cannot be zero", this->stepExp);
4111 }
4112 bool goingUp = step>0;
4113 Frame *f = runtimeEnv->pushIterationFrame(this);
4114 BOOST_SCOPE_EXIT( (runtimeEnv) ) {
4115 runtimeEnv->popFrame();
4116 } BOOST_SCOPE_EXIT_END
4117 VariableSlot &varSlot = f->varSlots.front();
4118 while( (goingUp && begin<=end) || (!goingUp && begin>=end)) {
4119 runtimeEnv->interpreter->checkForInterrupts(this);
4120 varSlot.value = new INT(begin);
4121 try {
4122 this->statements->execute(runtimeEnv);
4123 } catch (const Break &b) {
4124 if (b.label.length() && this->label!=b.label)
4125 throw;
4126 return;
4127 } catch (const Continue &c) {
4128 if (c.label.length() && this->label!=c.label)
4129 throw;
4130 }
4131 begin += step;
4132 }
4133 }
4134
implExecute(RuntimeEnvironment * runtimeEnv)4135 void Statements::implExecute(RuntimeEnvironment *runtimeEnv) {
4136 BOOST_FOREACH(intrusive_ptr<Statement> s, this->statements)
4137 s->execute(runtimeEnv);
4138 }
4139
implExecute(RuntimeEnvironment * runtimeEnv)4140 void ForeachStatement::implExecute(RuntimeEnvironment *runtimeEnv) {
4141 intrusive_ptr<LIST> list = this->inExp->evalAs<LIST>(runtimeEnv);
4142 Frame *f = runtimeEnv->pushIterationFrame(this);
4143 BOOST_SCOPE_EXIT( (runtimeEnv) ) {
4144 runtimeEnv->popFrame();
4145 } BOOST_SCOPE_EXIT_END
4146 VariableSlot &varSlot = f->varSlots.front();
4147 const int size = list->size();
4148 for(int a=0; a<size; ++a) {
4149 runtimeEnv->interpreter->checkForInterrupts(this);
4150 intrusive_ptr<RightValue> sourceElem = list->getValue(a);
4151 assert(sourceElem);
4152 varSlot.value = sourceElem;
4153 try {
4154 this->statements->execute(runtimeEnv);
4155 } catch (const Break &b) {
4156 if (b.label.length() && this->label!=b.label)
4157 throw;
4158 return;
4159 } catch (const Continue &c) {
4160 if (c.label.length() && this->label!=c.label)
4161 throw;
4162 continue;
4163 }
4164 }
4165 }
4166
implExecute(RuntimeEnvironment * runtimeEnv)4167 void TryStatement::implExecute(RuntimeEnvironment *runtimeEnv) {
4168 try {
4169 this->tryStatements->execute(runtimeEnv);
4170 } catch (InterruptException &) {
4171 throw;
4172 } catch (RuntimeException &exc) {
4173 Frame *f = runtimeEnv->pushIterationFrame(this);
4174 BOOST_SCOPE_EXIT( (runtimeEnv) ) {
4175 runtimeEnv->popFrame();
4176 } BOOST_SCOPE_EXIT_END
4177 VariableSlot &varSlot = f->varSlots.front();
4178 varSlot.value = new ERROR(exc.reason);
4179 this->uponErrorStatements->execute(runtimeEnv);
4180 }
4181 }
4182
implExecute(RuntimeEnvironment * runtimeEnv)4183 void BlockStatement::implExecute(RuntimeEnvironment *runtimeEnv) {
4184 this->statements->execute(runtimeEnv);
4185 }
4186
implExecute(RuntimeEnvironment *)4187 void AliasStatement::implExecute(RuntimeEnvironment *) {
4188 //if (this->statements)
4189 // this->statements->execute(runtimeEnv);
4190 }
4191
implExecute(RuntimeEnvironment * runtimeEnv)4192 void WhileStatement::implExecute(RuntimeEnvironment *runtimeEnv) {
4193 while(this->exp->evalAs<BOOL>(runtimeEnv)->theBool) {
4194 runtimeEnv->interpreter->checkForInterrupts(this);
4195 try {
4196 this->statements->execute(runtimeEnv);
4197 } catch (const Break &b) {
4198 if (b.label.length() && this->label!=b.label)
4199 throw;
4200 return;
4201 } catch (const Continue &c) {
4202 if (c.label.length() && this->label!=c.label)
4203 throw;
4204 }
4205 }
4206 }
4207
implExecute(RuntimeEnvironment * runtimeEnv)4208 void RepeatUntilStatement::implExecute(RuntimeEnvironment *runtimeEnv) {
4209 const bool forever = !this->optExp;
4210 do {
4211 runtimeEnv->interpreter->checkForInterrupts(this);
4212 try {
4213 this->statements->execute(runtimeEnv);
4214 } catch (const Break &b) {
4215 if (b.label.length() && this->label!=b.label)
4216 throw;
4217 return;
4218 } catch (const Continue &c) {
4219 if (c.label.length() && this->label!=c.label)
4220 throw;
4221 }
4222 } while(forever || !this->optExp->evalAs<BOOL>(runtimeEnv)->theBool);
4223 }
4224
4225 namespace {
findOwner(RuntimeEnvironment * runtimeEnv,string name)4226 intrusive_ptr<PackageValue> findOwner(RuntimeEnvironment *runtimeEnv, string name) {
4227 BOOST_FOREACH(const VariableSlot &vs, runtimeEnv->getTopLevelFrame()->varSlots) {
4228 if (intrusive_ptr<PackageValue> p = dynamic_pointer_cast<PackageValue>(vs.value)) {
4229 BOOST_FOREACH(const Token &t, p->pkgDecl->exportedNames) {
4230 if (t.lexeme()==name)
4231 return p;
4232 }
4233 }
4234 }
4235 return nullptr;
4236 }
4237 }
4238
implExecute(RuntimeEnvironment * runtimeEnv)4239 void PackageStatement::implExecute(RuntimeEnvironment *runtimeEnv) {
4240 Frame * const tlFrame = runtimeEnv->getTopLevelFrame();
4241 int tlIndex = runtimeEnv->slotFor(this->name);
4242 if (tlIndex>=0) {
4243 assert(tlFrame->varSlots[tlIndex].value);
4244 intrusive_ptr<PackageValue> oldPkg = intrusive_ptr_cast<PackageValue>(tlFrame->varSlots[tlIndex].value);
4245 runtimeEnv->interpreter->reportWarning("Package "+this->name+" has been redefined", this->beginSourcePosition, this->tokName.getEnd());
4246 BOOST_FOREACH(int index, oldPkg->ownedTopLevelIndexes) {
4247 assert(index>=0 && static_cast<vector<VariableSlot>::size_type >(index)<tlFrame->varSlots.size());
4248 VariableSlot &vs = tlFrame->varSlots[index];
4249 assert(vs.value);
4250 vs.resetFlags();
4251 vs.value = nullptr;
4252 }
4253 }
4254 const string protectionReason = "Owned by package "+this->name;
4255 intrusive_ptr<PackageValue> newPackage(new PackageValue(this));
4256 const int pkgIndex = runtimeEnv->setTopLevelVar(this->name, newPackage, VariableSlot::VSF_SystemProtected);
4257 tlFrame->varSlots[pkgIndex].setProtectionReason(protectionReason);
4258 ResolvePackageNamesVisitor rpnv(*this);
4259 typedef pair<string, intrusive_ptr<const AssignmentStatement> > Pair;
4260 vector<Pair> memberVars;
4261 BOOST_FOREACH(intrusive_ptr<Statement> statement, this->statements->statements) {
4262 if (dynamic_pointer_cast<const AliasStatement>(statement))
4263 continue;
4264 if (const intrusive_ptr<const AssignmentStatement> assignment = dynamic_pointer_cast<const AssignmentStatement>(statement)) {
4265 intrusive_ptr<Identifier> idExp = intrusive_ptr_cast<Identifier>(assignment->leftExp);
4266 const string identifier = this->name+"."+idExp->identifier;
4267 memberVars.push_back(make_pair(identifier, assignment));
4268 const int index = runtimeEnv->setTopLevelVar(identifier, VoidValue::theInstance, VariableSlot::VSF_None);
4269 newPackage->ownedTopLevelIndexes.push_back(index);
4270 } else if (const intrusive_ptr<const DefineStatement> define = dynamic_pointer_cast<const DefineStatement>(statement)) {
4271 define->funDecl->accept(&rpnv);
4272 const int index = runtimeEnv->setTopLevelVar(this->name+"."+define->name, new UserDefinedFunction(runtimeEnv, define->funDecl), VariableSlot::VSF_SystemProtected);
4273 newPackage->ownedTopLevelIndexes.push_back(index);
4274 tlFrame->varSlots[index].setProtectionReason(protectionReason);
4275 } else
4276 assert(false);
4277 }
4278 BOOST_FOREACH(const Token &tokName, this->exportedNames) {
4279 const string name(tokName.lexeme());
4280 int index = runtimeEnv->slotFor(name);
4281 if (index>=0) {
4282 if (tlFrame->varSlots[index].isProtected()) {
4283 runtimeEnv->interpreter->reportError("Cannot export the name \""+name+"\" because there is a top-level protected variable with the same name", tokName.getBegin(), tokName.getEnd());
4284 continue;
4285 }
4286 if (tlFrame->varSlots[index].isPackage()) {
4287 intrusive_ptr<PackageValue> owner = findOwner(runtimeEnv, name);
4288 assert(owner);
4289 runtimeEnv->interpreter->reportError("Cannot export the name \""+name+"\" because the same name was already exported by package "+owner->pkgName, tokName.getBegin(), tokName.getEnd());
4290 continue;
4291 }
4292 }
4293 const int indexFullyQualified = runtimeEnv->slotFor(this->name+"."+name);
4294 assert(indexFullyQualified>=0);
4295 index = runtimeEnv->setTopLevelVar(name, VoidValue::theInstance, VariableSlot::VSF_Package);
4296 newPackage->ownedTopLevelIndexes.push_back(index);
4297 intrusive_ptr<Identifier> id(new Identifier(tokName));
4298 id->varData.depth = StaticEnv::TOP_LEVEL;
4299 id->varData.index = indexFullyQualified;
4300 tlFrame->varSlots[index].value = new VariableName(runtimeEnv, tlFrame, indexFullyQualified, id);
4301 tlFrame->varSlots[indexFullyQualified].setHasBeenExported();
4302 }
4303 BOOST_FOREACH(const Pair &assignment, memberVars) {
4304 const intrusive_ptr<Expression> rightExp = assignment.second->rightExp;
4305 rightExp->accept(&rpnv);
4306 runtimeEnv->setTopLevelVar(assignment.first, rightExp->evalAs<RightValue>(runtimeEnv), VariableSlot::VSF_None);
4307 }
4308 }
4309
implExecute(RuntimeEnvironment * runtimeEnv)4310 void DefineStatement::implExecute(RuntimeEnvironment *runtimeEnv) {
4311 const intrusive_ptr<UserDefinedFunction> fun(new UserDefinedFunction(runtimeEnv, this->funDecl));
4312 int slotIndex = runtimeEnv->slotFor(this->name);
4313 if (slotIndex<0)
4314 runtimeEnv->setTopLevelVar(this->name, fun);
4315 else {
4316 VariableSlot *vs = &(runtimeEnv->getTopLevelFrame()->varSlots[slotIndex]);
4317 checkProtection(vs, this->expId);
4318 vs->value = fun;
4319 }
4320 }
4321
implEval(RuntimeEnvironment * runtimeEnv)4322 intrusive_ptr<Value> FullyQualifiedIdentifier::implEval(RuntimeEnvironment *runtimeEnv) const {
4323 const int slot = runtimeEnv->slotFor(this->pkgName);
4324 if (slot<0)
4325 throw RuntimeException("Cannot find package \""+this->pkgName+"\"", this->tokPkgname);
4326 assert(runtimeEnv->getTopLevelFrame()->varSlots[slot].value);
4327 const intrusive_ptr<PackageValue> pv(intrusive_ptr_cast<PackageValue>(runtimeEnv->getTopLevelFrame()->varSlots[slot].value));
4328 return pv->toVariableName(runtimeEnv, this->id, this->tokId);
4329 }
4330
implEval(RuntimeEnvironment * runtimeEnv)4331 intrusive_ptr<Value> LambdaExpression::implEval(RuntimeEnvironment *runtimeEnv) const {
4332 return new UserDefinedFunction(runtimeEnv, this->funDecl);
4333 }
4334
implExecute(RuntimeEnvironment * runtimeEnv)4335 void ReturnStatement::implExecute(RuntimeEnvironment *runtimeEnv) {
4336 throw Return(this->exp ? this->exp->evalAs<RightValue>(runtimeEnv) : VoidValue::theInstance);
4337 }
4338
implExecute(RuntimeEnvironment *)4339 void BreakStatement::implExecute(RuntimeEnvironment *) {
4340 throw Break(this->label);
4341 }
4342
implExecute(RuntimeEnvironment *)4343 void ContinueStatement::implExecute(RuntimeEnvironment *) {
4344 throw Continue(this->label);
4345 }
4346
implExecute(RuntimeEnvironment * runtimeEnv)4347 void AssignmentStatement::implExecute(RuntimeEnvironment *runtimeEnv) {
4348 const intrusive_ptr<LeftValue> leftValue = this->leftExp->evalAs<LeftValue>(runtimeEnv);
4349 runtimeEnv->interpreter->checkForInterrupts(this->leftExp);
4350 intrusive_ptr<RightValue> rightValue = this->rightExp->evalAs<RightValue>(runtimeEnv);
4351 if (leftValue->assignmentNeedsOwnership())
4352 leftValue->obtainOwnership();
4353 leftValue->assign(rightValue, this->rightExp->getBegin(), this->rightExp->getEnd(), runtimeEnv);
4354 }
4355
4356 } // namespace AST
4357
4358 namespace LexerNS {
4359
4360 using namespace InterpreterNS;
4361
reportError(const RuntimeException & exception)4362 void ErrorReporter::reportError(const RuntimeException &exception) {
4363 this->reportError(exception.reason, exception.from, exception.to);
4364 const vector<SnapshotFrame>::size_type snapshotSize = exception.snapshot.size();
4365 if (snapshotSize) {
4366 this->printContext();
4367 int nesting=-1;
4368 bool dots=false;
4369 CharPointer from = exception.from;
4370 CharPointer to = exception.to;
4371 for(vector<SnapshotFrame>::size_type a=0; a<snapshotSize; ++a) {
4372 const SnapshotFrame &frame = exception.snapshot[a];
4373 ++nesting;
4374 if ( (snapshotSize-a>10) && a>10 ) {
4375 if (dots) {
4376 --nesting;
4377 continue;
4378 }
4379 this->outputStream->print(string(nesting, ' '))->print("...\n");
4380 dots = true;
4381 continue;
4382 }
4383 if (nesting) {
4384 this->outputStream->print(string(nesting, ' '));
4385 this->printCalledBy();
4386 }
4387 const intrusive_ptr<const FunctionDeclaration> fnDecl(intrusive_ptr_cast<const FunctionDeclaration>(frame.block));
4388 if (fnDecl->fnName.length()) {
4389 this->outputStream->print("function ");
4390 this->printBold(fnDecl->fnName);
4391 } else
4392 this->printBold("anonymous-function");
4393 if (!this->reportLineNumberWhenMeaningful(from, to, false, false)) {
4394 if (frame.block)
4395 this->outputStream->print(" (previously defined at the prompt)");
4396 else
4397 this->outputStream->print(" at top-level");
4398 }
4399 this->outputStream->newline();
4400 from = frame.invocationExp->getBegin();
4401 to = frame.invocationExp->getEnd();
4402 }
4403 this->outputStream->print(string(++nesting, ' '))->print("called");
4404 if (!this->reportLineNumberWhenMeaningful(from, to, false, false))
4405 this->outputStream->print(" at top-level");
4406 this->outputStream->newline();
4407 }
4408 }
4409
reportInterrupt(const InterpreterNS::InterruptException & intr)4410 void ErrorReporter::reportInterrupt(const InterpreterNS::InterruptException &intr)
4411 {
4412 this->implReportInterrupt(intr.from, intr.to);
4413 }
4414
4415
4416 } // namespace LexerNS
4417
4418 } // namespace CoCoA
4419