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 &param, 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 &param = 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