1
2 #include "yacas/arggetter.h"
3 #include "yacas/arrayclass.h"
4 #include "yacas/associationclass.h"
5 #include "yacas/errors.h"
6 #include "yacas/infixparser.h"
7 #include "yacas/lispatom.h"
8 #include "yacas/lispenvironment.h"
9 #include "yacas/lisperror.h"
10 #include "yacas/lispeval.h"
11 #include "yacas/lispparser.h"
12 #include "yacas/lispuserfunc.h"
13 #include "yacas/mathuserfunc.h"
14 #include "yacas/numbers.h"
15 #include "yacas/patternclass.h"
16 #include "yacas/platfileio.h"
17 #include "yacas/platmath.h"
18 #include "yacas/standard.h"
19 #include "yacas/string_utils.h"
20 #include "yacas/stringio.h"
21 #include "yacas/substitute.h"
22
23 #include <cstring>
24 #include <limits.h>
25 #include <sstream>
26 #include <stdlib.h>
27 #include <string>
28
29 #ifdef _WIN32
30 # include <windows.h>
31 #else
32 # include <unistd.h>
33 #endif
34
35 #define InternalEval aEnvironment.iEvaluator->Eval
36 #define RESULT aEnvironment.iStack[aStackTop]
37 #define ARGUMENT(i) aEnvironment.iStack[aStackTop + i]
38
39 void LispLexCompare2(LispEnvironment& aEnvironment,
40 int aStackTop,
41 bool (*lexfunc)(const char* f1,
42 const char* f2,
43 LispHashTable& aHashTable,
44 int aPrecision),
45 bool (*numfunc)(BigNumber& n1, BigNumber& n2));
46
LispQuote(LispEnvironment & aEnvironment,int aStackTop)47 void LispQuote(LispEnvironment& aEnvironment, int aStackTop)
48 {
49 RESULT = (ARGUMENT(1)->Copy());
50 }
51
LispEval(LispEnvironment & aEnvironment,int aStackTop)52 void LispEval(LispEnvironment& aEnvironment, int aStackTop)
53 {
54 InternalEval(aEnvironment, RESULT, ARGUMENT(1));
55 }
56
57 /// Execute the Yacas commands \c Set and \c MacroSet.
58 /// The argument \a aMacroMode determines whether the first argument
59 /// should be evaluated. The real work is done by
60 /// LispEnvironment::SetVariable() .
61 /// \sa LispSetVar(), LispMacroSetVar()
InternalSetVar(LispEnvironment & aEnvironment,int aStackTop,bool aMacroMode,bool aGlobalLazyVariable)62 static void InternalSetVar(LispEnvironment& aEnvironment,
63 int aStackTop,
64 bool aMacroMode,
65 bool aGlobalLazyVariable)
66 {
67 const LispString* varstring = nullptr;
68 if (aMacroMode) {
69 LispPtr result;
70 InternalEval(aEnvironment, result, ARGUMENT(1));
71 varstring = result->String();
72 } else {
73 varstring = ARGUMENT(1)->String();
74 }
75 CheckArg(varstring, 1, aEnvironment, aStackTop);
76 CheckArg(!IsNumber(*varstring, true), 1, aEnvironment, aStackTop);
77
78 LispPtr result;
79 InternalEval(aEnvironment, result, ARGUMENT(2));
80 aEnvironment.SetVariable(varstring, result, aGlobalLazyVariable);
81 InternalTrue(aEnvironment, RESULT);
82 }
83
84 /// Corresponds to the Yacas function \c Set.
85 /// This function simply calls InternalSetVar() .
LispSetVar(LispEnvironment & aEnvironment,int aStackTop)86 void LispSetVar(LispEnvironment& aEnvironment, int aStackTop)
87 {
88 InternalSetVar(aEnvironment, aStackTop, false, false);
89 }
90
91 /// Corresponds to the Yacas function \c MacroSet.
92 /// This function simply calls InternalSetVar() .
LispMacroSetVar(LispEnvironment & aEnvironment,int aStackTop)93 void LispMacroSetVar(LispEnvironment& aEnvironment, int aStackTop)
94 {
95 InternalSetVar(aEnvironment, aStackTop, true, false);
96 }
97
LispSetGlobalLazyVariable(LispEnvironment & aEnvironment,int aStackTop)98 void LispSetGlobalLazyVariable(LispEnvironment& aEnvironment, int aStackTop)
99 {
100 InternalSetVar(aEnvironment, aStackTop, false, true);
101 }
102
LispClearVar(LispEnvironment & aEnvironment,int aStackTop)103 void LispClearVar(LispEnvironment& aEnvironment, int aStackTop)
104 {
105 LispPtr* subList = ARGUMENT(1)->SubList();
106 if (subList) {
107 LispIterator iter(*subList);
108 for (int nr = 1; (++iter).getObj(); nr++) {
109 const LispString* str = iter.getObj()->String();
110 CheckArg(str, nr, aEnvironment, aStackTop);
111 aEnvironment.UnsetVariable(str);
112 }
113 }
114 InternalTrue(aEnvironment, RESULT);
115 }
116
LispVars(LispEnvironment & aEnvironment,int aStackTop)117 void LispVars(LispEnvironment& aEnvironment, int aStackTop)
118 {
119 LispPtr vars;
120 aEnvironment.GlobalVariables(vars);
121 RESULT = vars;
122 }
123
124 /* StrCompare returns f1-f2: if f1 < f2 it returns -1, if f1=f2 it
125 returns 0, and it returns 1 if f1>f2
126 */
127 // the aPrecision argument is ignored here
LexLessThan(const char * f1,const char * f2,LispHashTable & aHashTable,int aPrecision)128 static bool LexLessThan(const char* f1,
129 const char* f2,
130 LispHashTable& aHashTable,
131 int aPrecision)
132 {
133 return (std::strcmp(f1, f2) < 0);
134 }
135
136 // the aPrecision argument is ignored here
LexGreaterThan(const char * f1,const char * f2,LispHashTable & aHashTable,int aPrecision)137 static bool LexGreaterThan(const char* f1,
138 const char* f2,
139 LispHashTable& aHashTable,
140 int aPrecision)
141 {
142 return (std::strcmp(f1, f2) > 0);
143 }
144
BigLessThan(BigNumber & n1,BigNumber & n2)145 static bool BigLessThan(BigNumber& n1, BigNumber& n2)
146 {
147 return n1.LessThan(n2) && !n1.Equals(n2);
148 }
BigGreaterThan(BigNumber & n1,BigNumber & n2)149 static bool BigGreaterThan(BigNumber& n1, BigNumber& n2)
150 {
151 return !(n1.LessThan(n2) || n1.Equals(n2));
152 }
153
LispStrictTotalOrder(LispEnvironment & aEnvironment,int aStackTop)154 void LispStrictTotalOrder(LispEnvironment& aEnvironment, int aStackTop)
155 {
156 LispPtr e1(ARGUMENT(1));
157 LispPtr e2(ARGUMENT(2));
158
159 InternalBoolean(
160 aEnvironment, RESULT, InternalStrictTotalOrder(aEnvironment, e1, e2));
161 }
162
LispLessThan(LispEnvironment & aEnvironment,int aStackTop)163 void LispLessThan(LispEnvironment& aEnvironment, int aStackTop)
164 {
165 LispLexCompare2(aEnvironment, aStackTop, LexLessThan, BigLessThan);
166 }
167
LispGreaterThan(LispEnvironment & aEnvironment,int aStackTop)168 void LispGreaterThan(LispEnvironment& aEnvironment, int aStackTop)
169 {
170 LispLexCompare2(aEnvironment, aStackTop, LexGreaterThan, BigGreaterThan);
171 }
172
LispLexCompare2(LispEnvironment & aEnvironment,int aStackTop,bool (* lexfunc)(const char * f1,const char * f2,LispHashTable & aHashTable,int aPrecision),bool (* numfunc)(BigNumber & n1,BigNumber & n2))173 void LispLexCompare2(LispEnvironment& aEnvironment,
174 int aStackTop,
175 bool (*lexfunc)(const char* f1,
176 const char* f2,
177 LispHashTable& aHashTable,
178 int aPrecision),
179 bool (*numfunc)(BigNumber& n1, BigNumber& n2))
180 {
181 LispPtr result1(ARGUMENT(1));
182 LispPtr result2(ARGUMENT(2));
183 bool cmp;
184 BigNumber* n1 = result1->Number(aEnvironment.Precision());
185 BigNumber* n2 = result2->Number(aEnvironment.Precision());
186 if (n1 && n2) {
187 cmp = numfunc(*n1, *n2);
188 } else {
189 const LispString* str1 = result1->String();
190 const LispString* str2 = result2->String();
191 CheckArg(str1, 1, aEnvironment, aStackTop);
192 CheckArg(str2, 2, aEnvironment, aStackTop);
193 // the precision argument is ignored in "lex" functions
194 cmp = lexfunc(str1->c_str(),
195 str2->c_str(),
196 aEnvironment.HashTable(),
197 aEnvironment.Precision());
198 }
199
200 InternalBoolean(aEnvironment, RESULT, cmp);
201 }
202
LispFullForm(LispEnvironment & aEnvironment,int aStackTop)203 void LispFullForm(LispEnvironment& aEnvironment, int aStackTop)
204 {
205 RESULT = (ARGUMENT(1));
206 LispPrinter printer;
207 printer.Print(RESULT, aEnvironment.CurrentOutput(), aEnvironment);
208 aEnvironment.CurrentOutput().put('\n');
209 }
210
LispHead(LispEnvironment & aEnvironment,int aStackTop)211 void LispHead(LispEnvironment& aEnvironment, int aStackTop)
212 {
213 InternalNth(RESULT, ARGUMENT(1), 1);
214 }
215
LispNth(LispEnvironment & aEnvironment,int aStackTop)216 void LispNth(LispEnvironment& aEnvironment, int aStackTop)
217 {
218 const LispString* str = ARGUMENT(2)->String();
219 CheckArg(str, 2, aEnvironment, aStackTop);
220 CheckArg(IsNumber(str->c_str(), false), 2, aEnvironment, aStackTop);
221 int index = InternalAsciiToInt(*str);
222 InternalNth(RESULT, ARGUMENT(1), index);
223 }
224
LispTail(LispEnvironment & aEnvironment,int aStackTop)225 void LispTail(LispEnvironment& aEnvironment, int aStackTop)
226 {
227 LispPtr first;
228 InternalTail(first, ARGUMENT(1));
229 InternalTail(RESULT, first);
230 LispPtr head(aEnvironment.iList->Copy());
231 head->Nixed() = ((*RESULT->SubList()));
232 (*RESULT->SubList()) = (head);
233 }
234
LispUnList(LispEnvironment & aEnvironment,int aStackTop)235 void LispUnList(LispEnvironment& aEnvironment, int aStackTop)
236 {
237 CheckArg(ARGUMENT(1), 1, aEnvironment, aStackTop);
238 CheckArg(ARGUMENT(1)->SubList(), 1, aEnvironment, aStackTop);
239 LispObject* subList = (*ARGUMENT(1)->SubList());
240 CheckArg(subList, 1, aEnvironment, aStackTop);
241 CheckArg(subList->String() == aEnvironment.iList->String(),
242 1,
243 aEnvironment,
244 aStackTop);
245 InternalTail(RESULT, ARGUMENT(1));
246 }
247
LispListify(LispEnvironment & aEnvironment,int aStackTop)248 void LispListify(LispEnvironment& aEnvironment, int aStackTop)
249 {
250 CheckArg(ARGUMENT(1)->SubList(), 1, aEnvironment, aStackTop);
251 LispPtr head(aEnvironment.iList->Copy());
252 head->Nixed() = ((*ARGUMENT(1)->SubList()));
253 RESULT = (LispSubList::New(head));
254 }
255
LispDestructiveReverse(LispEnvironment & aEnvironment,int aStackTop)256 void LispDestructiveReverse(LispEnvironment& aEnvironment, int aStackTop)
257 {
258 CheckArgIsList(1, aEnvironment, aStackTop);
259
260 LispPtr reversed(aEnvironment.iList->Copy());
261 InternalReverseList(reversed->Nixed(), (*ARGUMENT(1)->SubList())->Nixed());
262 RESULT = (LispSubList::New(reversed));
263 }
264
LispLength(LispEnvironment & aEnvironment,int aStackTop)265 void LispLength(LispEnvironment& aEnvironment, int aStackTop)
266 {
267 std::size_t size = 0;
268
269 if (LispPtr* subList = ARGUMENT(1)->SubList()) {
270 size = InternalListLength((*subList)->Nixed());
271 } else if (InternalIsString(ARGUMENT(1)->String())) {
272 size = ARGUMENT(1)->String()->size() - 2;
273 } else if (ArrayClass* arr =
274 dynamic_cast<ArrayClass*>(ARGUMENT(1)->Generic())) {
275 size = arr->Size();
276 } else if (AssociationClass* assoc =
277 dynamic_cast<AssociationClass*>(ARGUMENT(1)->Generic())) {
278 size = assoc->Size();
279 } else
280 CheckArg(false, 1, aEnvironment, aStackTop);
281
282 RESULT = LispAtom::New(aEnvironment, std::to_string(size));
283 }
284
LispList(LispEnvironment & aEnvironment,int aStackTop)285 void LispList(LispEnvironment& aEnvironment, int aStackTop)
286 {
287 LispPtr all(aEnvironment.iList->Copy());
288 LispIterator tail(all);
289 ++tail;
290 LispIterator iter(*ARGUMENT(1)->SubList());
291 while ((++iter).getObj()) {
292 LispPtr evaluated;
293 InternalEval(aEnvironment, evaluated, *iter);
294 // Ideally this would work, but it does not yet: (*tail++) = (evaluated)
295 (*tail) = (evaluated);
296 ++tail;
297 }
298 RESULT = (LispSubList::New(all));
299 }
300
LispConcatenate(LispEnvironment & aEnvironment,int aStackTop)301 void LispConcatenate(LispEnvironment& aEnvironment, int aStackTop)
302 {
303 LispPtr all(aEnvironment.iList->Copy());
304 LispIterator tail(all);
305 ++tail;
306 LispIterator iter(*ARGUMENT(1)->SubList());
307 for (int arg = 1; (++iter).getObj(); arg++) {
308 CheckArgIsList(*iter, arg, aEnvironment, aStackTop);
309 InternalFlatCopy(
310 *tail,
311 (*(*iter)->SubList())->Nixed()); // TODO: woof -- prefer below
312 // InternalFlatCopy(*tail,iter.getObj()->Nixed());
313 while (tail.getObj())
314 ++tail;
315 }
316 RESULT = (LispSubList::New(all));
317 }
318
LispConcatenateStrings(LispEnvironment & aEnvironment,int aStackTop)319 void LispConcatenateStrings(LispEnvironment& aEnvironment, int aStackTop)
320 {
321 std::string s;
322 s.push_back('\"');
323
324 int arg = 1;
325 for (LispIterator iter(*ARGUMENT(1)->SubList()); (++iter).getObj();) {
326 CheckArgIsString(*iter, arg++, aEnvironment, aStackTop);
327 const std::string& p = *iter.getObj()->String();
328 s.append(p.substr(1, p.size() - 2));
329 }
330 s.push_back('\"');
331
332 RESULT = LispAtom::New(aEnvironment, s);
333 }
334
335 static void
InternalDelete(LispEnvironment & aEnvironment,int aStackTop,int aDestructive)336 InternalDelete(LispEnvironment& aEnvironment, int aStackTop, int aDestructive)
337 {
338 LispPtr evaluated(ARGUMENT(1));
339 CheckArgIsList(1, aEnvironment, aStackTop);
340
341 LispPtr copied;
342 if (aDestructive) {
343 copied = ((*evaluated->SubList()));
344 } else {
345 InternalFlatCopy(copied, *evaluated->SubList());
346 }
347
348 LispPtr index(ARGUMENT(2));
349 CheckArg(index, 2, aEnvironment, aStackTop);
350 CheckArg(index->String(), 2, aEnvironment, aStackTop);
351 int ind = InternalAsciiToInt(*index->String());
352 CheckArg(ind > 0, 2, aEnvironment, aStackTop);
353
354 LispIterator iter(copied);
355 while (--ind >= 0)
356 ++iter;
357 if (!iter.getObj()) {
358 ShowStack(aEnvironment);
359 throw LispErrListNotLongEnough();
360 }
361 LispIterator temp = iter++;
362 (*temp) = (*iter);
363 RESULT = (LispSubList::New(copied));
364 }
365
LispDelete(LispEnvironment & aEnvironment,int aStackTop)366 void LispDelete(LispEnvironment& aEnvironment, int aStackTop)
367 {
368 InternalDelete(aEnvironment, aStackTop, false);
369 }
370
LispDestructiveDelete(LispEnvironment & aEnvironment,int aStackTop)371 void LispDestructiveDelete(LispEnvironment& aEnvironment, int aStackTop)
372 {
373 InternalDelete(aEnvironment, aStackTop, true);
374 }
375
LispFlatCopy(LispEnvironment & aEnvironment,int aStackTop)376 void LispFlatCopy(LispEnvironment& aEnvironment, int aStackTop)
377 {
378 LispPtr copied;
379
380 if (ARGUMENT(1)->SubList() == nullptr)
381 CheckArgIsList(1, aEnvironment, aStackTop);
382
383 InternalFlatCopy(copied, *ARGUMENT(1)->SubList());
384 RESULT = (LispSubList::New(copied));
385 }
386
387 static void
InternalInsert(LispEnvironment & aEnvironment,int aStackTop,int aDestructive)388 InternalInsert(LispEnvironment& aEnvironment, int aStackTop, int aDestructive)
389 {
390 CheckArgIsList(1, aEnvironment, aStackTop);
391
392 LispPtr evaluated(ARGUMENT(1));
393
394 LispPtr copied;
395 if (aDestructive) {
396 copied = ((*evaluated->SubList()));
397 } else {
398 InternalFlatCopy(copied, *evaluated->SubList());
399 }
400
401 LispPtr index(ARGUMENT(2));
402 CheckArg(index, 2, aEnvironment, aStackTop);
403 CheckArg(index->String(), 2, aEnvironment, aStackTop);
404 int ind = InternalAsciiToInt(*index->String());
405 CheckArg(ind > 0, 2, aEnvironment, aStackTop);
406
407 LispIterator iter(copied);
408 while (--ind >= 0)
409 ++iter;
410 LispPtr toInsert(ARGUMENT(3));
411 toInsert->Nixed() = (iter.getObj());
412 (*iter) = (toInsert);
413 RESULT = (LispSubList::New(copied));
414 }
415
LispInsert(LispEnvironment & aEnvironment,int aStackTop)416 void LispInsert(LispEnvironment& aEnvironment, int aStackTop)
417 {
418 InternalInsert(aEnvironment, aStackTop, false);
419 }
420
LispDestructiveInsert(LispEnvironment & aEnvironment,int aStackTop)421 void LispDestructiveInsert(LispEnvironment& aEnvironment, int aStackTop)
422 {
423 InternalInsert(aEnvironment, aStackTop, true);
424 }
425
426 static void
InternalReplace(LispEnvironment & aEnvironment,int aStackTop,int aDestructive)427 InternalReplace(LispEnvironment& aEnvironment, int aStackTop, int aDestructive)
428 {
429 LispPtr evaluated(ARGUMENT(1));
430 // CHK_ISLIST_CORE(evaluated,1);
431 // Ok, so lets not check if it is a list, but it needs to be at least a
432 // 'function'
433 CheckArg(evaluated->SubList(), 1, aEnvironment, aStackTop);
434
435 LispPtr index(ARGUMENT(2));
436 CheckArg(index, 2, aEnvironment, aStackTop);
437 CheckArg(index->String(), 2, aEnvironment, aStackTop);
438 int ind = InternalAsciiToInt(*index->String());
439
440 LispPtr copied;
441 if (aDestructive) {
442 copied = ((*evaluated->SubList()));
443 } else {
444 InternalFlatCopy(copied, *evaluated->SubList());
445 }
446 CheckArg(ind > 0, 2, aEnvironment, aStackTop);
447
448 LispIterator iter(copied);
449 while (--ind >= 0)
450 ++iter;
451 LispPtr toInsert(ARGUMENT(3));
452 CheckArg(iter.getObj(), 2, aEnvironment, aStackTop);
453
454 LispIterator temp = iter++;
455 toInsert->Nixed() = (*iter);
456 (*temp) = (toInsert);
457 RESULT = (LispSubList::New(copied));
458 }
459
LispReplace(LispEnvironment & aEnvironment,int aStackTop)460 void LispReplace(LispEnvironment& aEnvironment, int aStackTop)
461 {
462 InternalReplace(aEnvironment, aStackTop, false);
463 }
464
LispDestructiveReplace(LispEnvironment & aEnvironment,int aStackTop)465 void LispDestructiveReplace(LispEnvironment& aEnvironment, int aStackTop)
466 {
467 InternalReplace(aEnvironment, aStackTop, true);
468 }
469
LispNot(LispEnvironment & aEnvironment,int aStackTop)470 void LispNot(LispEnvironment& aEnvironment, int aStackTop)
471 {
472 LispPtr evaluated(ARGUMENT(1));
473 if (IsTrue(aEnvironment, evaluated) || IsFalse(aEnvironment, evaluated)) {
474 InternalNot(RESULT, aEnvironment, evaluated);
475 } else {
476 LispPtr ptr(ARGUMENT(0)->Copy());
477 ptr->Nixed() = (evaluated);
478 RESULT = (LispSubList::New(ptr));
479 }
480 }
481
LispLazyAnd(LispEnvironment & aEnvironment,int aStackTop)482 void LispLazyAnd(LispEnvironment& aEnvironment, int aStackTop)
483 {
484 LispPtr nogos;
485 int nrnogos = 0;
486 LispPtr evaluated;
487
488 LispIterator iter(*ARGUMENT(1)->SubList());
489 while ((++iter).getObj()) {
490 InternalEval(aEnvironment, evaluated, *iter);
491 if (IsFalse(aEnvironment, evaluated)) {
492 InternalFalse(aEnvironment, RESULT);
493 return;
494 } else if (!IsTrue(aEnvironment, evaluated)) {
495 nrnogos++;
496 LispPtr ptr(evaluated->Copy());
497 ptr->Nixed() = (nogos);
498 nogos = (ptr);
499 }
500 }
501
502 if (!!nogos) {
503 if (nrnogos == 1) {
504 RESULT = (nogos);
505 } else {
506 LispPtr ptr;
507 InternalReverseList(ptr, nogos);
508 nogos = (ptr);
509
510 ptr = (ARGUMENT(0)->Copy());
511 ptr->Nixed() = (nogos);
512 nogos = (ptr);
513 RESULT = (LispSubList::New(nogos));
514 // aEnvironment.CurrentPrinter().Print(RESULT,
515 // *aEnvironment.CurrentOutput());
516 }
517 } else {
518 InternalTrue(aEnvironment, RESULT);
519 }
520 }
521
LispLazyOr(LispEnvironment & aEnvironment,int aStackTop)522 void LispLazyOr(LispEnvironment& aEnvironment, int aStackTop)
523 {
524 LispPtr nogos;
525 int nrnogos = 0;
526
527 LispPtr evaluated;
528
529 LispIterator iter(*ARGUMENT(1)->SubList());
530 while ((++iter).getObj()) {
531 InternalEval(aEnvironment, evaluated, *iter);
532 if (IsTrue(aEnvironment, evaluated)) {
533 InternalTrue(aEnvironment, RESULT);
534 return;
535 } else if (!IsFalse(aEnvironment, evaluated)) {
536 nrnogos++;
537 LispPtr ptr(evaluated->Copy());
538 ptr->Nixed() = (nogos);
539 nogos = (ptr);
540 }
541 }
542
543 if (!!nogos) {
544 if (nrnogos == 1) {
545 RESULT = (nogos);
546 } else {
547 LispPtr ptr;
548 InternalReverseList(ptr, nogos);
549 nogos = (ptr);
550
551 ptr = (ARGUMENT(0)->Copy());
552 ptr->Nixed() = (nogos);
553 nogos = (ptr);
554 RESULT = (LispSubList::New(nogos));
555 }
556 // aEnvironment.CurrentPrinter().Print(RESULT,
557 // *aEnvironment.CurrentOutput());
558 } else {
559 InternalFalse(aEnvironment, RESULT);
560 }
561 }
562
LispEquals(LispEnvironment & aEnvironment,int aStackTop)563 void LispEquals(LispEnvironment& aEnvironment, int aStackTop)
564 {
565 LispPtr evaluated1(ARGUMENT(1));
566 LispPtr evaluated2(ARGUMENT(2));
567
568 InternalBoolean(aEnvironment,
569 RESULT,
570 InternalEquals(aEnvironment, evaluated1, evaluated2));
571 }
572
LispWrite(LispEnvironment & aEnvironment,int aStackTop)573 void LispWrite(LispEnvironment& aEnvironment, int aStackTop)
574 {
575 LispPtr* subList = ARGUMENT(1)->SubList();
576 if (subList) {
577 LispIterator iter(*subList);
578 while ((++iter).getObj()) {
579 aEnvironment.CurrentPrinter().Print(
580 *iter, aEnvironment.CurrentOutput(), aEnvironment);
581 }
582 }
583 InternalTrue(aEnvironment, RESULT);
584 }
585
LispWriteString(LispEnvironment & aEnvironment,int aStackTop)586 void LispWriteString(LispEnvironment& aEnvironment, int aStackTop)
587 {
588 CheckArg(ARGUMENT(1), 1, aEnvironment, aStackTop);
589 const LispString* str = ARGUMENT(1)->String();
590 CheckArg(str, 1, aEnvironment, aStackTop);
591 CheckArg((*str)[0] == '\"', 1, aEnvironment, aStackTop);
592 CheckArg((*str)[str->size() - 1] == '\"', 1, aEnvironment, aStackTop);
593
594 const std::size_t nr = str->size() - 1;
595 //((*str)[i] != '\"')
596 for (std::size_t i = 1; i < nr; ++i)
597 aEnvironment.CurrentOutput().put((*str)[i]);
598
599 // pass last printed character to the current printer
600 aEnvironment.CurrentPrinter().RememberLastChar(
601 (*str)[nr - 1]); // hacky hacky
602 InternalTrue(aEnvironment, RESULT);
603 }
604
LispProgBody(LispEnvironment & aEnvironment,int aStackTop)605 void LispProgBody(LispEnvironment& aEnvironment, int aStackTop)
606 {
607 // Allow accessing previous locals.
608 LispLocalFrame frame(aEnvironment, false);
609
610 InternalTrue(aEnvironment, RESULT);
611
612 // Evaluate args one by one.
613
614 LispIterator iter(*ARGUMENT(1)->SubList());
615 while ((++iter).getObj()) {
616 InternalEval(aEnvironment, RESULT, *iter);
617 }
618 }
619
LispNewLocal(LispEnvironment & aEnvironment,int aStackTop)620 void LispNewLocal(LispEnvironment& aEnvironment, int aStackTop)
621 {
622 LispPtr* subList = ARGUMENT(1)->SubList();
623 if (subList) {
624 LispIterator iter(*subList);
625 for (int nr = 1; (++iter).getObj(); nr++) {
626 const LispString* variable = iter.getObj()->String();
627 CheckArg(variable, nr, aEnvironment, aStackTop);
628 // printf("Variable %s\n",variable->String());
629 aEnvironment.NewLocal(variable, nullptr);
630 }
631 }
632 InternalTrue(aEnvironment, RESULT);
633 }
634
LispWhile(LispEnvironment & aEnvironment,int aStackTop)635 void LispWhile(LispEnvironment& aEnvironment, int aStackTop)
636 {
637 LispPtr& arg1 = ARGUMENT(1);
638 LispPtr& arg2 = ARGUMENT(2);
639
640 LispPtr predicate;
641 InternalEval(aEnvironment, predicate, arg1);
642
643 while (IsTrue(aEnvironment, predicate)) {
644 LispPtr evaluated;
645 InternalEval(aEnvironment, evaluated, arg2);
646 InternalEval(aEnvironment, predicate, arg1);
647 }
648 CheckArg(IsFalse(aEnvironment, predicate), 1, aEnvironment, aStackTop);
649 InternalTrue(aEnvironment, RESULT);
650 }
651
652 static void
MultiFix(LispEnvironment & aEnvironment,int aStackTop,LispOperators & aOps)653 MultiFix(LispEnvironment& aEnvironment, int aStackTop, LispOperators& aOps)
654 {
655
656 // Get operator
657 CheckArg(ARGUMENT(1), 1, aEnvironment, aStackTop);
658 const LispString* orig = ARGUMENT(1)->String();
659 CheckArg(orig, 1, aEnvironment, aStackTop);
660
661 LispPtr precedence;
662 InternalEval(aEnvironment, precedence, ARGUMENT(2));
663 CheckArg(precedence->String(), 2, aEnvironment, aStackTop);
664 int prec = InternalAsciiToInt(*precedence->String());
665 CheckArg(prec <= KMaxPrecedence, 2, aEnvironment, aStackTop);
666 aOps[SymbolName(aEnvironment, *orig)] = LispInFixOperator(prec);
667 InternalTrue(aEnvironment, RESULT);
668 }
669
LispInFix(LispEnvironment & aEnvironment,int aStackTop)670 void LispInFix(LispEnvironment& aEnvironment, int aStackTop)
671 {
672 MultiFix(aEnvironment, aStackTop, aEnvironment.InFix());
673 }
674
SingleFix(int aPrecedence,LispEnvironment & aEnvironment,int aStackTop,LispOperators & aOps)675 static void SingleFix(int aPrecedence,
676 LispEnvironment& aEnvironment,
677 int aStackTop,
678 LispOperators& aOps)
679 {
680 // Get operator
681 CheckArg(ARGUMENT(1), 1, aEnvironment, aStackTop);
682 const LispString* orig = ARGUMENT(1)->String();
683 CheckArg(orig, 1, aEnvironment, aStackTop);
684 aOps[SymbolName(aEnvironment, *orig)] = LispInFixOperator(aPrecedence);
685 InternalTrue(aEnvironment, RESULT);
686 }
687
LispPreFix(LispEnvironment & aEnvironment,int aStackTop)688 void LispPreFix(LispEnvironment& aEnvironment, int aStackTop)
689 {
690 /*
691 int nrArguments = InternalListLength(ARGUMENT(0));
692 if (nrArguments == 2)
693 {
694 SingleFix(0, aEnvironment, aStackTop, aEnvironment.PreFix());
695 }
696 else
697 */
698 {
699 MultiFix(aEnvironment, aStackTop, aEnvironment.PreFix());
700 }
701 }
702
LispPostFix(LispEnvironment & aEnvironment,int aStackTop)703 void LispPostFix(LispEnvironment& aEnvironment, int aStackTop)
704 {
705 const std::size_t nrArguments = InternalListLength(ARGUMENT(0));
706 if (nrArguments == 2)
707 SingleFix(0, aEnvironment, aStackTop, aEnvironment.PostFix());
708 else
709 MultiFix(aEnvironment, aStackTop, aEnvironment.PostFix());
710 }
711
LispBodied(LispEnvironment & aEnvironment,int aStackTop)712 void LispBodied(LispEnvironment& aEnvironment, int aStackTop)
713 {
714 MultiFix(aEnvironment, aStackTop, aEnvironment.Bodied());
715 }
716
LispAtomize(LispEnvironment & aEnvironment,int aStackTop)717 void LispAtomize(LispEnvironment& aEnvironment, int aStackTop)
718 {
719 LispPtr evaluated(ARGUMENT(1));
720
721 // Get operator
722 CheckArg(evaluated, 1, aEnvironment, aStackTop);
723 const LispString* orig = evaluated->String();
724 CheckArg(orig, 1, aEnvironment, aStackTop);
725 RESULT = LispAtom::New(aEnvironment, orig->substr(1, orig->length() - 2));
726 }
727
LispStringify(LispEnvironment & aEnvironment,int aStackTop)728 void LispStringify(LispEnvironment& aEnvironment, int aStackTop)
729 {
730 LispPtr evaluated(ARGUMENT(1));
731
732 // Get operator
733 CheckArg(evaluated, 1, aEnvironment, aStackTop);
734 const LispString* orig = evaluated->String();
735 CheckArg(orig, 1, aEnvironment, aStackTop);
736
737 RESULT = LispAtom::New(aEnvironment, stringify(*orig));
738 }
739
LispLoad(LispEnvironment & aEnvironment,int aStackTop)740 void LispLoad(LispEnvironment& aEnvironment, int aStackTop)
741 {
742 CheckSecure(aEnvironment, aStackTop);
743
744 LispPtr evaluated(ARGUMENT(1));
745
746 // Get file name
747 CheckArg(evaluated, 1, aEnvironment, aStackTop);
748 const LispString* orig = evaluated->String();
749 CheckArg(orig, 1, aEnvironment, aStackTop);
750
751 InternalLoad(aEnvironment, *orig);
752 InternalTrue(aEnvironment, RESULT);
753 }
754
LispTmpFile(LispEnvironment & aEnvironment,int aStackTop)755 void LispTmpFile(LispEnvironment& aEnvironment, int aStackTop)
756 {
757 CheckSecure(aEnvironment, aStackTop);
758
759 #ifndef _WIN32
760 char fn[] = "/tmp/yacas-XXXXXX";
761
762 int fd = mkstemp(fn);
763
764 // FIXME: not very clear
765 if (fd < 0) {
766 ShowStack(aEnvironment);
767 throw LispErrFileNotFound();
768 }
769
770 close(fd);
771 RESULT = LispAtom::New(aEnvironment, stringify(fn));
772
773 #else
774 char tmp_path[MAX_PATH];
775 char tmp_fn[MAX_PATH];
776
777 GetTempPath(MAX_PATH, tmp_path);
778 GetTempFileName(tmp_path, "yacas", 0, tmp_fn);
779
780 RESULT = LispAtom::New(aEnvironment, stringify(tmp_fn));
781 #endif
782 }
783
LispProtect(LispEnvironment & env,int top)784 void LispProtect(LispEnvironment& env, int top)
785 {
786 LispPtr p(env.iStack[top + 1]);
787
788 CheckArg(p, 1, env, top);
789 const LispString* s = p->String();
790 CheckArg(s, 1, env, top);
791
792 env.Protect(s);
793
794 InternalTrue(env, env.iStack[top]);
795 }
796
LispUnProtect(LispEnvironment & env,int top)797 void LispUnProtect(LispEnvironment& env, int top)
798 {
799 LispPtr p(env.iStack[top + 1]);
800
801 CheckArg(p, 1, env, top);
802 const LispString* s = p->String();
803 CheckArg(s, 1, env, top);
804
805 env.UnProtect(s);
806
807 InternalTrue(env, env.iStack[top]);
808 }
809
LispIsProtected(LispEnvironment & env,int top)810 void LispIsProtected(LispEnvironment& env, int top)
811 {
812 LispPtr p(env.iStack[top + 1]);
813
814 CheckArg(p, 1, env, top);
815 const LispString* s = p->String();
816 CheckArg(s, 1, env, top);
817
818 env.iStack[top] = env.Protected(s) ? env.iTrue->Copy() : env.iFalse->Copy();
819 }
820
821 /// Implements the Yacas functions \c RuleBase and \c MacroRuleBase .
822 /// The real work is done by LispEnvironment::DeclareRuleBase().
823 static void
InternalRuleBase(LispEnvironment & aEnvironment,int aStackTop,int aListed)824 InternalRuleBase(LispEnvironment& aEnvironment, int aStackTop, int aListed)
825 {
826 // Get operator
827
828 CheckArg(ARGUMENT(1), 1, aEnvironment, aStackTop);
829 const LispString* orig = ARGUMENT(1)->String();
830 CheckArg(orig, 1, aEnvironment, aStackTop);
831 LispPtr args(ARGUMENT(2));
832
833 // The arguments
834 CheckArgIsList(2, aEnvironment, aStackTop);
835
836 // Finally define the rule base
837 aEnvironment.DeclareRuleBase(
838 SymbolName(aEnvironment, *orig), (*args->SubList())->Nixed(), aListed);
839
840 // Return true
841 InternalTrue(aEnvironment, RESULT);
842 }
843
844 /// Corresponds to the Yacas function \c RuleBase .
845 /// This function simply calls InternalRuleBase().
LispRuleBase(LispEnvironment & aEnvironment,int aStackTop)846 void LispRuleBase(LispEnvironment& aEnvironment, int aStackTop)
847 {
848 InternalRuleBase(aEnvironment, aStackTop, false);
849 }
850
LispMacroRuleBase(LispEnvironment & aEnvironment,int aStackTop)851 void LispMacroRuleBase(LispEnvironment& aEnvironment, int aStackTop)
852 {
853 InternalRuleBase(aEnvironment, aStackTop, false);
854 }
855
InternalDefMacroRuleBase(LispEnvironment & aEnvironment,int aStackTop,int aListed)856 void InternalDefMacroRuleBase(LispEnvironment& aEnvironment,
857 int aStackTop,
858 int aListed)
859 {
860 // Get operator
861 // LispPtr body;
862
863 CheckArg(ARGUMENT(1), 1, aEnvironment, aStackTop);
864 const LispString* orig = ARGUMENT(1)->String();
865 CheckArg(orig, 1, aEnvironment, aStackTop);
866
867 // The arguments
868 LispPtr args(ARGUMENT(2));
869 CheckArgIsList(2, aEnvironment, aStackTop);
870
871 // Finally define the rule base
872 aEnvironment.DeclareMacroRuleBase(
873 SymbolName(aEnvironment, *orig), (*args->SubList())->Nixed(), aListed);
874
875 // Return true
876 InternalTrue(aEnvironment, RESULT);
877 }
878
LispDefMacroRuleBaseListed(LispEnvironment & aEnvironment,int aStackTop)879 void LispDefMacroRuleBaseListed(LispEnvironment& aEnvironment, int aStackTop)
880 {
881 InternalDefMacroRuleBase(aEnvironment, aStackTop, true);
882 }
883
LispDefMacroRuleBase(LispEnvironment & aEnvironment,int aStackTop)884 void LispDefMacroRuleBase(LispEnvironment& aEnvironment, int aStackTop)
885 {
886 InternalDefMacroRuleBase(aEnvironment, aStackTop, false);
887 }
888
LispRuleBaseListed(LispEnvironment & aEnvironment,int aStackTop)889 void LispRuleBaseListed(LispEnvironment& aEnvironment, int aStackTop)
890 {
891 InternalRuleBase(aEnvironment, aStackTop, true);
892 }
893
LispMacroRuleBaseListed(LispEnvironment & aEnvironment,int aStackTop)894 void LispMacroRuleBaseListed(LispEnvironment& aEnvironment, int aStackTop)
895 {
896 InternalRuleBase(aEnvironment, aStackTop, true);
897 }
898
LispHoldArg(LispEnvironment & aEnvironment,int aStackTop)899 void LispHoldArg(LispEnvironment& aEnvironment, int aStackTop)
900 {
901 // Get operator
902 CheckArg(ARGUMENT(1), 1, aEnvironment, aStackTop);
903 const LispString* orig = ARGUMENT(1)->String();
904 CheckArg(orig, 1, aEnvironment, aStackTop);
905
906 // The arguments
907 const LispString* tohold = ARGUMENT(2)->String();
908 CheckArg(tohold, 2, aEnvironment, aStackTop);
909 aEnvironment.HoldArgument(SymbolName(aEnvironment, *orig), tohold);
910 // Return true
911 InternalTrue(aEnvironment, RESULT);
912 }
913
InternalNewRule(LispEnvironment & aEnvironment,int aStackTop)914 static void InternalNewRule(LispEnvironment& aEnvironment, int aStackTop)
915 {
916 int arity;
917 int precedence;
918
919 LispPtr ar;
920 LispPtr pr;
921 LispPtr predicate;
922 LispPtr body;
923
924 // Get operator
925 CheckArg(ARGUMENT(1), 1, aEnvironment, aStackTop);
926 const LispString* orig = ARGUMENT(1)->String();
927 CheckArg(orig, 1, aEnvironment, aStackTop);
928 ar = (ARGUMENT(2));
929 pr = (ARGUMENT(3));
930 predicate = (ARGUMENT(4));
931 body = (ARGUMENT(5));
932
933 // The arity
934 CheckArg(ar, 2, aEnvironment, aStackTop);
935 CheckArg(ar->String(), 2, aEnvironment, aStackTop);
936 arity = InternalAsciiToInt(*ar->String());
937
938 // The precedence
939 CheckArg(pr, 3, aEnvironment, aStackTop);
940 CheckArg(pr->String(), 3, aEnvironment, aStackTop);
941 precedence = InternalAsciiToInt(*pr->String());
942
943 // Finally define the rule base
944 aEnvironment.DefineRule(
945 SymbolName(aEnvironment, *orig), arity, precedence, predicate, body);
946
947 // Return true
948 InternalTrue(aEnvironment, RESULT);
949 }
950
LispNewRule(LispEnvironment & aEnvironment,int aStackTop)951 void LispNewRule(LispEnvironment& aEnvironment, int aStackTop)
952 {
953 InternalNewRule(aEnvironment, aStackTop);
954 }
955
LispMacroNewRule(LispEnvironment & aEnvironment,int aStackTop)956 void LispMacroNewRule(LispEnvironment& aEnvironment, int aStackTop)
957 {
958 InternalNewRule(aEnvironment, aStackTop);
959 }
960
LispUnFence(LispEnvironment & aEnvironment,int aStackTop)961 void LispUnFence(LispEnvironment& aEnvironment, int aStackTop)
962 {
963 // Get operator
964 CheckArg(ARGUMENT(1), 1, aEnvironment, aStackTop);
965 const LispString* orig = ARGUMENT(1)->String();
966 CheckArg(orig, 1, aEnvironment, aStackTop);
967
968 // The arity
969 CheckArg(ARGUMENT(2), 2, aEnvironment, aStackTop);
970 CheckArg(ARGUMENT(2)->String(), 2, aEnvironment, aStackTop);
971 int arity = InternalAsciiToInt(*ARGUMENT(2)->String());
972
973 aEnvironment.UnFenceRule(SymbolName(aEnvironment, *orig), arity);
974
975 // Return true
976 InternalTrue(aEnvironment, RESULT);
977 }
978
LispIsFunction(LispEnvironment & aEnvironment,int aStackTop)979 void LispIsFunction(LispEnvironment& aEnvironment, int aStackTop)
980 {
981 LispPtr result(ARGUMENT(1));
982 InternalBoolean(aEnvironment, RESULT, result->SubList() != nullptr);
983 }
984
LispIsAtom(LispEnvironment & aEnvironment,int aStackTop)985 void LispIsAtom(LispEnvironment& aEnvironment, int aStackTop)
986 {
987 LispPtr result(ARGUMENT(1));
988 InternalBoolean(aEnvironment, RESULT, result->String() != nullptr);
989 }
990
LispIsNumber(LispEnvironment & aEnvironment,int aStackTop)991 void LispIsNumber(LispEnvironment& aEnvironment, int aStackTop)
992 {
993 LispPtr result(ARGUMENT(1));
994 InternalBoolean(aEnvironment,
995 RESULT,
996 result->Number(aEnvironment.Precision()) != nullptr);
997 }
998
LispIsInteger(LispEnvironment & aEnvironment,int aStackTop)999 void LispIsInteger(LispEnvironment& aEnvironment, int aStackTop)
1000 {
1001 LispPtr result(ARGUMENT(1));
1002
1003 BigNumber* num(result->Number(aEnvironment.Precision()));
1004 InternalBoolean(aEnvironment, RESULT, num && num->IsInt());
1005 }
1006
LispIsList(LispEnvironment & aEnvironment,int aStackTop)1007 void LispIsList(LispEnvironment& aEnvironment, int aStackTop)
1008 {
1009 LispPtr result(ARGUMENT(1));
1010 InternalBoolean(aEnvironment, RESULT, InternalIsList(aEnvironment, result));
1011 }
1012
LispIsString(LispEnvironment & aEnvironment,int aStackTop)1013 void LispIsString(LispEnvironment& aEnvironment, int aStackTop)
1014 {
1015 LispPtr result(ARGUMENT(1));
1016 InternalBoolean(aEnvironment, RESULT, InternalIsString(result->String()));
1017 }
1018
LispIsBound(LispEnvironment & aEnvironment,int aStackTop)1019 void LispIsBound(LispEnvironment& aEnvironment, int aStackTop)
1020 {
1021 const LispString* str = ARGUMENT(1)->String();
1022 if (str) {
1023 LispPtr val;
1024 aEnvironment.GetVariable(str, val);
1025 if (!!val) {
1026 InternalTrue(aEnvironment, RESULT);
1027 return;
1028 }
1029 }
1030 InternalFalse(aEnvironment, RESULT);
1031 }
1032
LispIf(LispEnvironment & aEnvironment,int aStackTop)1033 void LispIf(LispEnvironment& aEnvironment, int aStackTop)
1034 {
1035 int nrArguments = InternalListLength(ARGUMENT(0));
1036 if (nrArguments != 3 && nrArguments != 4) {
1037 ShowStack(aEnvironment);
1038 throw LispErrWrongNumberOfArgs();
1039 }
1040
1041 LispPtr predicate;
1042 InternalEval(aEnvironment, predicate, ARGUMENT(1));
1043
1044 if (IsTrue(aEnvironment, predicate)) {
1045 InternalEval(aEnvironment, RESULT, Argument(ARGUMENT(0), 2));
1046 } else {
1047 CheckArg(IsFalse(aEnvironment, predicate), 1, aEnvironment, aStackTop);
1048 if (nrArguments == 4)
1049 InternalEval(aEnvironment, RESULT, Argument(ARGUMENT(0), 3));
1050 else
1051 InternalFalse(aEnvironment, RESULT);
1052 }
1053 }
1054
LispRetract(LispEnvironment & aEnvironment,int aStackTop)1055 void LispRetract(LispEnvironment& aEnvironment, int aStackTop)
1056 {
1057 // Get operator
1058 LispPtr evaluated(ARGUMENT(1));
1059
1060 CheckArg(evaluated, 1, aEnvironment, aStackTop);
1061 const LispString* orig = evaluated->String();
1062 CheckArg(orig, 1, aEnvironment, aStackTop);
1063 const LispString* oper = SymbolName(aEnvironment, *orig);
1064
1065 LispPtr arity(ARGUMENT(2));
1066 CheckArg(arity->String(), 2, aEnvironment, aStackTop);
1067 int ar = InternalAsciiToInt(*arity->String());
1068 aEnvironment.Retract(oper, ar);
1069 InternalTrue(aEnvironment, RESULT);
1070 }
1071
YacasBuiltinPrecisionSet(LispEnvironment & aEnvironment,int aStackTop)1072 void YacasBuiltinPrecisionSet(LispEnvironment& aEnvironment, int aStackTop)
1073 {
1074 LispPtr index(ARGUMENT(1));
1075 CheckArg(index, 1, aEnvironment, aStackTop);
1076 CheckArg(index->String(), 1, aEnvironment, aStackTop);
1077
1078 int ind = InternalAsciiToInt(*index->String());
1079 CheckArg(ind > 0, 1, aEnvironment, aStackTop);
1080 aEnvironment.SetPrecision(ind);
1081 InternalTrue(aEnvironment, RESULT);
1082 }
1083
LispDefaultDirectory(LispEnvironment & aEnvironment,int aStackTop)1084 void LispDefaultDirectory(LispEnvironment& aEnvironment, int aStackTop)
1085 {
1086 // Get file name
1087 CheckArg(ARGUMENT(1), 1, aEnvironment, aStackTop);
1088 const LispString* orig = ARGUMENT(1)->String();
1089 CheckArg(orig, 1, aEnvironment, aStackTop);
1090 aEnvironment.iInputDirectories.push_back(InternalUnstringify(*orig));
1091 InternalTrue(aEnvironment, RESULT);
1092 }
1093
LispFromFile(LispEnvironment & aEnvironment,int aStackTop)1094 void LispFromFile(LispEnvironment& aEnvironment, int aStackTop)
1095 {
1096 CheckSecure(aEnvironment, aStackTop);
1097
1098 LispPtr evaluated;
1099 InternalEval(aEnvironment, evaluated, ARGUMENT(1));
1100
1101 // Get file name
1102 CheckArg(evaluated, 1, aEnvironment, aStackTop);
1103 const LispString* orig = evaluated->String();
1104 CheckArg(orig, 1, aEnvironment, aStackTop);
1105
1106 const std::string fname = orig->substr(1, orig->length() - 2);
1107
1108 InputStatus oldstatus = aEnvironment.iInputStatus;
1109 aEnvironment.iInputStatus.SetTo(fname);
1110
1111 // Open file
1112 LispLocalFile localFP(
1113 aEnvironment, fname, true, aEnvironment.iInputDirectories);
1114 if (!localFP.stream.is_open()) {
1115 ShowStack(aEnvironment);
1116 throw LispErrFileNotFound();
1117 }
1118 StdFileInput newInput(localFP, aEnvironment.iInputStatus);
1119 LispLocalInput localInput(aEnvironment, &newInput);
1120
1121 // Evaluate the body
1122 InternalEval(aEnvironment, RESULT, ARGUMENT(2));
1123
1124 aEnvironment.iInputStatus.RestoreFrom(oldstatus);
1125 // Return the result
1126 }
1127
LispFromString(LispEnvironment & aEnvironment,int aStackTop)1128 void LispFromString(LispEnvironment& aEnvironment, int aStackTop)
1129 {
1130 LispPtr evaluated;
1131 InternalEval(aEnvironment, evaluated, ARGUMENT(1));
1132
1133 // Get file name
1134 CheckArg(evaluated, 1, aEnvironment, aStackTop);
1135 const LispString* orig = evaluated->String();
1136 CheckArg(orig, 1, aEnvironment, aStackTop);
1137 const std::string oper = InternalUnstringify(*orig);
1138
1139 InputStatus oldstatus = aEnvironment.iInputStatus;
1140 aEnvironment.iInputStatus.SetTo("String");
1141 StringInput newInput(oper, aEnvironment.iInputStatus);
1142 LispLocalInput localInput(aEnvironment, &newInput);
1143
1144 // Evaluate the body
1145 InternalEval(aEnvironment, RESULT, ARGUMENT(2));
1146 aEnvironment.iInputStatus.RestoreFrom(oldstatus);
1147
1148 // Return the result
1149 }
1150
LispRead(LispEnvironment & aEnvironment,int aStackTop)1151 void LispRead(LispEnvironment& aEnvironment, int aStackTop)
1152 {
1153 LispTokenizer& tok = *aEnvironment.iCurrentTokenizer;
1154 InfixParser parser(tok,
1155 *aEnvironment.CurrentInput(),
1156 aEnvironment,
1157 aEnvironment.PreFix(),
1158 aEnvironment.InFix(),
1159 aEnvironment.PostFix(),
1160 aEnvironment.Bodied());
1161 // Read expression
1162 parser.Parse(RESULT);
1163 }
1164
LispReadToken(LispEnvironment & aEnvironment,int aStackTop)1165 void LispReadToken(LispEnvironment& aEnvironment, int aStackTop)
1166 {
1167 LispTokenizer& tok = *aEnvironment.iCurrentTokenizer;
1168 const LispString* result = aEnvironment.HashTable().LookUp(
1169 tok.NextToken(*aEnvironment.CurrentInput()));
1170
1171 if (result->empty()) {
1172 RESULT = aEnvironment.iEndOfFile->Copy();
1173 return;
1174 }
1175 RESULT = LispAtom::New(aEnvironment, *result);
1176 }
1177
LispToFile(LispEnvironment & aEnvironment,int aStackTop)1178 void LispToFile(LispEnvironment& aEnvironment, int aStackTop)
1179 {
1180 CheckSecure(aEnvironment, aStackTop);
1181
1182 LispPtr evaluated;
1183 InternalEval(aEnvironment, evaluated, ARGUMENT(1));
1184
1185 // Get file name
1186 CheckArg(evaluated, 1, aEnvironment, aStackTop);
1187 const LispString* orig = evaluated->String();
1188 CheckArg(orig, 1, aEnvironment, aStackTop);
1189 const std::string oper = InternalUnstringify(*orig);
1190
1191 // Open file for writing
1192 LispLocalFile localFP(
1193 aEnvironment, oper, false, aEnvironment.iInputDirectories);
1194 if (!localFP.stream.is_open()) {
1195 ShowStack(aEnvironment);
1196 throw LispErrFileNotFound();
1197 }
1198 LispLocalOutput localOutput(aEnvironment, localFP.stream);
1199
1200 // Evaluate the body
1201 InternalEval(aEnvironment, RESULT, ARGUMENT(2));
1202
1203 // Return the result
1204 }
1205
LispCheck(LispEnvironment & aEnvironment,int aStackTop)1206 void LispCheck(LispEnvironment& aEnvironment, int aStackTop)
1207 {
1208 LispPtr pred;
1209 InternalEval(aEnvironment, pred, ARGUMENT(1));
1210 if (!IsTrue(aEnvironment, pred)) {
1211 LispPtr evaluated;
1212 InternalEval(aEnvironment, evaluated, ARGUMENT(2));
1213 CheckArgIsString(evaluated, 2, aEnvironment, aStackTop);
1214 ShowStack(aEnvironment);
1215 throw LispErrUser(*evaluated->String());
1216 }
1217 RESULT = pred;
1218 }
1219
LispTrapError(LispEnvironment & aEnvironment,int aStackTop)1220 void LispTrapError(LispEnvironment& aEnvironment, int aStackTop)
1221 {
1222 try {
1223 InternalEval(aEnvironment, RESULT, ARGUMENT(1));
1224 } catch (const LispError& error) {
1225 HandleError(error, aEnvironment, aEnvironment.iErrorOutput);
1226 }
1227
1228 if (!aEnvironment.iErrorOutput.str().empty()) {
1229 InternalEval(aEnvironment, RESULT, ARGUMENT(2));
1230 aEnvironment.iErrorOutput.clear();
1231 aEnvironment.iErrorOutput.str("");
1232 }
1233 }
1234
LispGetCoreError(LispEnvironment & aEnvironment,int aStackTop)1235 void LispGetCoreError(LispEnvironment& aEnvironment, int aStackTop)
1236 {
1237 RESULT =
1238 LispAtom::New(aEnvironment, stringify(aEnvironment.iErrorOutput.str()));
1239 }
1240
LispSystemCall(LispEnvironment & aEnvironment,int aStackTop)1241 void LispSystemCall(LispEnvironment& aEnvironment, int aStackTop)
1242 {
1243 CheckSecure(aEnvironment, aStackTop);
1244
1245 LispPtr result(ARGUMENT(1));
1246 CheckArgIsString(1, aEnvironment, aStackTop);
1247
1248 const std::string command = InternalUnstringify(*result->String());
1249
1250 // we would like to pass the exit code back to Yacas. Right now, let's pass
1251 // True/False according to whether the exit code is 0 or not.
1252 InternalBoolean(aEnvironment, RESULT, system(command.c_str()) == 0);
1253 }
1254
LispSystemName(LispEnvironment & aEnvironment,int aStackTop)1255 void LispSystemName(LispEnvironment& aEnvironment, int aStackTop)
1256 {
1257 const char* s = "Unknown";
1258
1259 #if defined(_WIN32)
1260 s = "Windows";
1261 #elif defined(__APPLE__)
1262 s = "MacOSX";
1263 #elif defined(__linux__)
1264 s = "Linux";
1265 #endif
1266
1267 RESULT = LispAtom::New(aEnvironment, stringify(s));
1268 }
1269
LispMaxEvalDepth(LispEnvironment & aEnvironment,int aStackTop)1270 void LispMaxEvalDepth(LispEnvironment& aEnvironment, int aStackTop)
1271 {
1272 LispPtr index(ARGUMENT(1));
1273 CheckArg(index, 1, aEnvironment, aStackTop);
1274 CheckArg(index->String(), 1, aEnvironment, aStackTop);
1275
1276 int ind = InternalAsciiToInt(*index->String());
1277 aEnvironment.iMaxEvalDepth = ind;
1278 InternalTrue(aEnvironment, RESULT);
1279 }
1280
LispDefLoad(LispEnvironment & aEnvironment,int aStackTop)1281 void LispDefLoad(LispEnvironment& aEnvironment, int aStackTop)
1282 {
1283 CheckSecure(aEnvironment, aStackTop);
1284
1285 LispPtr evaluated(ARGUMENT(1));
1286
1287 // Get file name
1288 CheckArg(evaluated, 1, aEnvironment, aStackTop);
1289 const LispString* orig = evaluated->String();
1290 CheckArg(orig, 1, aEnvironment, aStackTop);
1291
1292 LoadDefFile(aEnvironment, *orig);
1293 InternalTrue(aEnvironment, RESULT);
1294 }
1295
LispUse(LispEnvironment & aEnvironment,int aStackTop)1296 void LispUse(LispEnvironment& aEnvironment, int aStackTop)
1297 {
1298 LispPtr evaluated(ARGUMENT(1));
1299
1300 // Get file name
1301 CheckArg(evaluated, 1, aEnvironment, aStackTop);
1302 const LispString* orig = evaluated->String();
1303 CheckArg(orig, 1, aEnvironment, aStackTop);
1304
1305 InternalUse(aEnvironment, *orig);
1306 InternalTrue(aEnvironment, RESULT);
1307 }
1308
LispRightAssociative(LispEnvironment & aEnvironment,int aStackTop)1309 void LispRightAssociative(LispEnvironment& aEnvironment, int aStackTop)
1310 {
1311 // Get operator
1312 CheckArg(ARGUMENT(1), 1, aEnvironment, aStackTop);
1313 const LispString* orig = ARGUMENT(1)->String();
1314 CheckArg(orig, 1, aEnvironment, aStackTop);
1315
1316 LispOperators::iterator opi =
1317 aEnvironment.InFix().find(SymbolName(aEnvironment, *orig));
1318 if (opi == aEnvironment.InFix().end())
1319 throw LispErrNotAnInFixOperator();
1320 opi->second.SetRightAssociative();
1321
1322 InternalTrue(aEnvironment, RESULT);
1323 }
1324
LispLeftPrecedence(LispEnvironment & aEnvironment,int aStackTop)1325 void LispLeftPrecedence(LispEnvironment& aEnvironment, int aStackTop)
1326 {
1327 // Get operator
1328 CheckArg(ARGUMENT(1), 1, aEnvironment, aStackTop);
1329 const LispString* orig = ARGUMENT(1)->String();
1330 CheckArg(orig, 1, aEnvironment, aStackTop);
1331
1332 LispPtr index;
1333 InternalEval(aEnvironment, index, ARGUMENT(2));
1334 CheckArg(index, 2, aEnvironment, aStackTop);
1335 CheckArg(index->String(), 2, aEnvironment, aStackTop);
1336 int ind = InternalAsciiToInt(*index->String());
1337
1338 LispOperators::iterator opi =
1339 aEnvironment.InFix().find(SymbolName(aEnvironment, *orig));
1340 if (opi == aEnvironment.InFix().end())
1341 throw LispErrNotAnInFixOperator();
1342 opi->second.SetLeftPrecedence(ind);
1343
1344 InternalTrue(aEnvironment, RESULT);
1345 }
1346
LispRightPrecedence(LispEnvironment & aEnvironment,int aStackTop)1347 void LispRightPrecedence(LispEnvironment& aEnvironment, int aStackTop)
1348 {
1349 // Get operator
1350 CheckArg(ARGUMENT(1), 1, aEnvironment, aStackTop);
1351 const LispString* orig = ARGUMENT(1)->String();
1352 CheckArg(orig, 1, aEnvironment, aStackTop);
1353
1354 LispPtr index;
1355 InternalEval(aEnvironment, index, ARGUMENT(2));
1356 CheckArg(index, 2, aEnvironment, aStackTop);
1357 CheckArg(index->String(), 2, aEnvironment, aStackTop);
1358 int ind = InternalAsciiToInt(*index->String());
1359
1360 LispOperators::iterator opi =
1361 aEnvironment.InFix().find(SymbolName(aEnvironment, *orig));
1362 if (opi == aEnvironment.InFix().end())
1363 throw LispErrNotAnInFixOperator();
1364 opi->second.SetRightPrecedence(ind);
1365
1366 InternalTrue(aEnvironment, RESULT);
1367 }
1368
OperatorInfo(LispEnvironment & aEnvironment,int aStackTop,LispOperators & aOperators)1369 static LispInFixOperator* OperatorInfo(LispEnvironment& aEnvironment,
1370 int aStackTop,
1371 LispOperators& aOperators)
1372 {
1373 // Get operator
1374 CheckArg(ARGUMENT(1), 1, aEnvironment, aStackTop);
1375
1376 LispPtr evaluated(ARGUMENT(1));
1377
1378 const LispString* orig = evaluated->String();
1379 CheckArg(orig, 1, aEnvironment, aStackTop);
1380
1381 const LispOperators::iterator opi =
1382 aOperators.find(SymbolName(aEnvironment, *orig));
1383 if (opi != aOperators.end())
1384 return &opi->second;
1385 return nullptr;
1386 }
1387
LispIsInFix(LispEnvironment & aEnvironment,int aStackTop)1388 void LispIsInFix(LispEnvironment& aEnvironment, int aStackTop)
1389 {
1390 LispInFixOperator* op =
1391 OperatorInfo(aEnvironment, aStackTop, aEnvironment.InFix());
1392 InternalBoolean(aEnvironment, RESULT, op != nullptr);
1393 }
1394
LispIsBodied(LispEnvironment & aEnvironment,int aStackTop)1395 void LispIsBodied(LispEnvironment& aEnvironment, int aStackTop)
1396 {
1397 LispInFixOperator* op =
1398 OperatorInfo(aEnvironment, aStackTop, aEnvironment.Bodied());
1399 InternalBoolean(aEnvironment, RESULT, op != nullptr);
1400 }
1401
LispGetPrecedence(LispEnvironment & aEnvironment,int aStackTop)1402 void LispGetPrecedence(LispEnvironment& aEnvironment, int aStackTop)
1403 {
1404 LispInFixOperator* op =
1405 OperatorInfo(aEnvironment, aStackTop, aEnvironment.InFix());
1406 if (!op) { // also need to check for a postfix or prefix operator
1407 op = OperatorInfo(aEnvironment, aStackTop, aEnvironment.PreFix());
1408 if (!op) {
1409 op = OperatorInfo(aEnvironment, aStackTop, aEnvironment.PostFix());
1410 if (!op) { // or maybe it's a bodied function
1411 op = OperatorInfo(
1412 aEnvironment, aStackTop, aEnvironment.Bodied());
1413 if (!op) {
1414 ShowStack(aEnvironment);
1415 throw LispErrIsNotInFix();
1416 }
1417 }
1418 }
1419 }
1420 RESULT = LispAtom::New(aEnvironment, std::to_string(op->iPrecedence));
1421 }
1422
LispGetLeftPrecedence(LispEnvironment & aEnvironment,int aStackTop)1423 void LispGetLeftPrecedence(LispEnvironment& aEnvironment, int aStackTop)
1424 {
1425 LispInFixOperator* op =
1426 OperatorInfo(aEnvironment, aStackTop, aEnvironment.InFix());
1427 if (!op) { // infix and postfix operators have left precedence
1428 op = OperatorInfo(aEnvironment, aStackTop, aEnvironment.PostFix());
1429 if (!op) {
1430 ShowStack(aEnvironment);
1431 throw LispErrIsNotInFix();
1432 }
1433 }
1434
1435 RESULT = LispAtom::New(aEnvironment, std::to_string(op->iLeftPrecedence));
1436 }
1437
LispGetRightPrecedence(LispEnvironment & aEnvironment,int aStackTop)1438 void LispGetRightPrecedence(LispEnvironment& aEnvironment, int aStackTop)
1439 {
1440 LispInFixOperator* op =
1441 OperatorInfo(aEnvironment, aStackTop, aEnvironment.InFix());
1442 if (!op) { // bodied, infix and prefix operators have right precedence
1443 op = OperatorInfo(aEnvironment, aStackTop, aEnvironment.PreFix());
1444 if (!op) { // or maybe it's a bodied function
1445 op = OperatorInfo(aEnvironment, aStackTop, aEnvironment.Bodied());
1446 if (!op) {
1447 ShowStack(aEnvironment);
1448 throw LispErrIsNotInFix();
1449 }
1450 }
1451 }
1452
1453 RESULT = LispAtom::New(aEnvironment, std::to_string(op->iRightPrecedence));
1454 }
1455
LispIsPreFix(LispEnvironment & aEnvironment,int aStackTop)1456 void LispIsPreFix(LispEnvironment& aEnvironment, int aStackTop)
1457 {
1458 LispInFixOperator* op =
1459 OperatorInfo(aEnvironment, aStackTop, aEnvironment.PreFix());
1460 InternalBoolean(aEnvironment, RESULT, op != nullptr);
1461 }
1462
LispIsPostFix(LispEnvironment & aEnvironment,int aStackTop)1463 void LispIsPostFix(LispEnvironment& aEnvironment, int aStackTop)
1464 {
1465 LispInFixOperator* op =
1466 OperatorInfo(aEnvironment, aStackTop, aEnvironment.PostFix());
1467
1468 InternalBoolean(aEnvironment, RESULT, op != nullptr);
1469 }
1470
YacasBuiltinPrecisionGet(LispEnvironment & aEnvironment,int aStackTop)1471 void YacasBuiltinPrecisionGet(LispEnvironment& aEnvironment, int aStackTop)
1472 {
1473 RESULT =
1474 LispAtom::New(aEnvironment, std::to_string(aEnvironment.Precision()));
1475 }
1476
LispToString(LispEnvironment & aEnvironment,int aStackTop)1477 void LispToString(LispEnvironment& aEnvironment, int aStackTop)
1478 {
1479 std::ostringstream os;
1480
1481 LispLocalOutput localOutput(aEnvironment, os);
1482
1483 // Evaluate the body
1484 InternalEval(aEnvironment, RESULT, ARGUMENT(1));
1485
1486 // Return the result
1487 RESULT = LispAtom::New(aEnvironment, stringify(os.str()));
1488 }
1489
LispToStdout(LispEnvironment & aEnvironment,int aStackTop)1490 void LispToStdout(LispEnvironment& aEnvironment, int aStackTop)
1491 {
1492 LispLocalOutput localOutput(aEnvironment, *aEnvironment.iInitialOutput);
1493 // Evaluate the body
1494 InternalEval(aEnvironment, RESULT, ARGUMENT(1));
1495 }
1496
LispSecure(LispEnvironment & aEnvironment,int aStackTop)1497 void LispSecure(LispEnvironment& aEnvironment, int aStackTop)
1498 {
1499 LispSecureFrame security(aEnvironment);
1500 InternalEval(aEnvironment, RESULT, ARGUMENT(1));
1501 }
1502
LispFindFile(LispEnvironment & aEnvironment,int aStackTop)1503 void LispFindFile(LispEnvironment& aEnvironment, int aStackTop)
1504 {
1505 CheckSecure(aEnvironment, aStackTop);
1506
1507 LispPtr evaluated(ARGUMENT(1));
1508
1509 // Get file name
1510 CheckArg(evaluated, 1, aEnvironment, aStackTop);
1511 const LispString* orig = evaluated->String();
1512 CheckArg(orig, 1, aEnvironment, aStackTop);
1513 const std::string oper = InternalUnstringify(*orig);
1514
1515 const std::string path =
1516 InternalFindFile(oper, aEnvironment.iInputDirectories);
1517
1518 RESULT = LispAtom::New(aEnvironment, stringify(path));
1519 }
1520
LispIsGeneric(LispEnvironment & aEnvironment,int aStackTop)1521 void LispIsGeneric(LispEnvironment& aEnvironment, int aStackTop)
1522 {
1523 LispPtr evaluated(ARGUMENT(1));
1524
1525 InternalBoolean(aEnvironment, RESULT, evaluated->Generic() != nullptr);
1526 }
1527
LispGenericTypeName(LispEnvironment & aEnvironment,int aStackTop)1528 void LispGenericTypeName(LispEnvironment& aEnvironment, int aStackTop)
1529 {
1530 LispPtr evaluated(ARGUMENT(1));
1531 CheckArg(evaluated, 1, aEnvironment, aStackTop);
1532
1533 const char* name = evaluated->Generic()->TypeName();
1534 RESULT = (LispAtom::New(aEnvironment, name));
1535 }
1536
GenArrayCreate(LispEnvironment & aEnvironment,int aStackTop)1537 void GenArrayCreate(LispEnvironment& aEnvironment, int aStackTop)
1538 {
1539 LispPtr sizearg(ARGUMENT(1));
1540
1541 CheckArg(sizearg, 1, aEnvironment, aStackTop);
1542 CheckArg(sizearg->String(), 1, aEnvironment, aStackTop);
1543
1544 int size = InternalAsciiToInt(*sizearg->String());
1545
1546 LispPtr initarg(ARGUMENT(2));
1547
1548 ArrayClass* array = new ArrayClass(size, initarg);
1549 RESULT = (LispGenericClass::New(array));
1550 }
1551
GenArraySize(LispEnvironment & aEnvironment,int aStackTop)1552 void GenArraySize(LispEnvironment& aEnvironment, int aStackTop)
1553 {
1554 LispPtr evaluated(ARGUMENT(1));
1555
1556 GenericClass* gen = evaluated->Generic();
1557 ArrayClass* arr = dynamic_cast<ArrayClass*>(gen);
1558 CheckArg(arr, 1, aEnvironment, aStackTop);
1559 RESULT = LispAtom::New(aEnvironment, std::to_string(arr->Size()));
1560 }
1561
GenArrayGet(LispEnvironment & aEnvironment,int aStackTop)1562 void GenArrayGet(LispEnvironment& aEnvironment, int aStackTop)
1563 {
1564 LispPtr evaluated(ARGUMENT(1));
1565
1566 GenericClass* gen = evaluated->Generic();
1567 ArrayClass* arr = dynamic_cast<ArrayClass*>(gen);
1568 CheckArg(arr, 1, aEnvironment, aStackTop);
1569
1570 LispPtr sizearg(ARGUMENT(2));
1571 CheckArg(sizearg, 2, aEnvironment, aStackTop);
1572 CheckArg(sizearg->String(), 2, aEnvironment, aStackTop);
1573
1574 int size = InternalAsciiToInt(*sizearg->String());
1575
1576 CheckArg(size > 0 && static_cast<std::size_t>(size) <= arr->Size(),
1577 2,
1578 aEnvironment,
1579 aStackTop);
1580 LispObject* object = arr->GetElement(size);
1581 RESULT = (object->Copy());
1582 }
1583
GenArraySet(LispEnvironment & aEnvironment,int aStackTop)1584 void GenArraySet(LispEnvironment& aEnvironment, int aStackTop)
1585 {
1586 LispPtr evaluated(ARGUMENT(1));
1587
1588 GenericClass* gen = evaluated->Generic();
1589 ArrayClass* arr = dynamic_cast<ArrayClass*>(gen);
1590 CheckArg(arr, 1, aEnvironment, aStackTop);
1591
1592 LispPtr sizearg(ARGUMENT(2));
1593 CheckArg(sizearg, 2, aEnvironment, aStackTop);
1594 CheckArg(sizearg->String(), 2, aEnvironment, aStackTop);
1595
1596 int size = InternalAsciiToInt(*sizearg->String());
1597
1598 CheckArg(size > 0 && static_cast<std::size_t>(size) <= arr->Size(),
1599 2,
1600 aEnvironment,
1601 aStackTop);
1602 LispPtr obj(ARGUMENT(3));
1603 arr->SetElement(size, obj);
1604
1605 InternalTrue(aEnvironment, RESULT);
1606 }
1607
GenAssociationCreate(LispEnvironment & aEnvironment,int aStackTop)1608 void GenAssociationCreate(LispEnvironment& aEnvironment, int aStackTop)
1609 {
1610 AssociationClass* a = new AssociationClass(aEnvironment);
1611 RESULT = LispGenericClass::New(a);
1612 }
1613
GenAssociationSize(LispEnvironment & aEnvironment,int aStackTop)1614 void GenAssociationSize(LispEnvironment& aEnvironment, int aStackTop)
1615 {
1616 LispPtr evaluated(ARGUMENT(1));
1617
1618 GenericClass* gen = evaluated->Generic();
1619 AssociationClass* a = dynamic_cast<AssociationClass*>(gen);
1620 CheckArg(a, 1, aEnvironment, aStackTop);
1621 RESULT = LispAtom::New(aEnvironment, std::to_string(a->Size()));
1622 }
1623
GenAssociationContains(LispEnvironment & aEnvironment,int aStackTop)1624 void GenAssociationContains(LispEnvironment& aEnvironment, int aStackTop)
1625 {
1626 LispPtr p(ARGUMENT(1));
1627 GenericClass* gen = p->Generic();
1628 AssociationClass* a = dynamic_cast<AssociationClass*>(gen);
1629 CheckArg(a, 1, aEnvironment, aStackTop);
1630
1631 LispPtr k(ARGUMENT(2));
1632
1633 if (a->GetElement(k))
1634 InternalTrue(aEnvironment, RESULT);
1635 else
1636 InternalFalse(aEnvironment, RESULT);
1637 }
1638
GenAssociationGet(LispEnvironment & aEnvironment,int aStackTop)1639 void GenAssociationGet(LispEnvironment& aEnvironment, int aStackTop)
1640 {
1641 LispPtr p(ARGUMENT(1));
1642 GenericClass* gen = p->Generic();
1643 AssociationClass* a = dynamic_cast<AssociationClass*>(gen);
1644 CheckArg(a, 1, aEnvironment, aStackTop);
1645
1646 LispPtr k(ARGUMENT(2));
1647 LispObject* v = a->GetElement(k);
1648
1649 if (v)
1650 RESULT = v->Copy();
1651 else
1652 RESULT = LispAtom::New(aEnvironment, "Undefined");
1653 }
1654
GenAssociationSet(LispEnvironment & aEnvironment,int aStackTop)1655 void GenAssociationSet(LispEnvironment& aEnvironment, int aStackTop)
1656 {
1657 LispPtr p(ARGUMENT(1));
1658 GenericClass* gen = p->Generic();
1659 AssociationClass* a = dynamic_cast<AssociationClass*>(gen);
1660 CheckArg(a, 1, aEnvironment, aStackTop);
1661
1662 LispPtr k(ARGUMENT(2));
1663 LispPtr v(ARGUMENT(3));
1664
1665 a->SetElement(k, v);
1666
1667 InternalTrue(aEnvironment, RESULT);
1668 }
1669
GenAssociationDrop(LispEnvironment & aEnvironment,int aStackTop)1670 void GenAssociationDrop(LispEnvironment& aEnvironment, int aStackTop)
1671 {
1672 LispPtr p(ARGUMENT(1));
1673 GenericClass* gen = p->Generic();
1674 AssociationClass* a = dynamic_cast<AssociationClass*>(gen);
1675 CheckArg(a, 1, aEnvironment, aStackTop);
1676
1677 LispPtr k(ARGUMENT(2));
1678 if (a->DropElement(k))
1679 InternalTrue(aEnvironment, RESULT);
1680 else
1681 InternalFalse(aEnvironment, RESULT);
1682 }
1683
GenAssociationKeys(LispEnvironment & aEnvironment,int aStackTop)1684 void GenAssociationKeys(LispEnvironment& aEnvironment, int aStackTop)
1685 {
1686 LispPtr p(ARGUMENT(1));
1687 GenericClass* gen = p->Generic();
1688 AssociationClass* a = dynamic_cast<AssociationClass*>(gen);
1689 CheckArg(a, 1, aEnvironment, aStackTop);
1690
1691 RESULT = a->Keys();
1692 }
1693
GenAssociationToList(LispEnvironment & aEnvironment,int aStackTop)1694 void GenAssociationToList(LispEnvironment& aEnvironment, int aStackTop)
1695 {
1696 LispPtr p(ARGUMENT(1));
1697 GenericClass* gen = p->Generic();
1698 AssociationClass* a = dynamic_cast<AssociationClass*>(gen);
1699 CheckArg(a, 1, aEnvironment, aStackTop);
1700
1701 RESULT = a->ToList();
1702 }
1703
GenAssociationHead(LispEnvironment & aEnvironment,int aStackTop)1704 void GenAssociationHead(LispEnvironment& aEnvironment, int aStackTop)
1705 {
1706 LispPtr p(ARGUMENT(1));
1707 GenericClass* gen = p->Generic();
1708 AssociationClass* a = dynamic_cast<AssociationClass*>(gen);
1709 CheckArg(a, 1, aEnvironment, aStackTop);
1710 CheckArg(a->Size(), 1, aEnvironment, aStackTop);
1711
1712 RESULT = a->Head();
1713 }
1714
LispCustomEval(LispEnvironment & aEnvironment,int aStackTop)1715 void LispCustomEval(LispEnvironment& aEnvironment, int aStackTop)
1716 {
1717 if (aEnvironment.iDebugger)
1718 delete aEnvironment.iDebugger;
1719 aEnvironment.iDebugger =
1720 new DefaultDebugger(ARGUMENT(1), ARGUMENT(2), ARGUMENT(3));
1721 LispLocalEvaluator local(aEnvironment, new TracedEvaluator);
1722 aEnvironment.iDebugger->Start();
1723 InternalEval(aEnvironment, RESULT, ARGUMENT(4));
1724 aEnvironment.iDebugger->Finish();
1725 delete aEnvironment.iDebugger;
1726 aEnvironment.iDebugger = nullptr;
1727 }
1728
LispCustomEvalExpression(LispEnvironment & aEnvironment,int aStackTop)1729 void LispCustomEvalExpression(LispEnvironment& aEnvironment, int aStackTop)
1730 {
1731 if (!aEnvironment.iDebugger)
1732 throw LispErrGeneric(
1733 "Trying to get CustomEval results while not in custom evaluation");
1734
1735 RESULT = (aEnvironment.iDebugger->iTopExpr);
1736 }
1737
LispCustomEvalResult(LispEnvironment & aEnvironment,int aStackTop)1738 void LispCustomEvalResult(LispEnvironment& aEnvironment, int aStackTop)
1739 {
1740 if (!aEnvironment.iDebugger)
1741 throw LispErrGeneric(
1742 "Trying to get CustomEval results while not in custom evaluation");
1743
1744 RESULT = (aEnvironment.iDebugger->iTopResult);
1745 }
1746
LispCustomEvalLocals(LispEnvironment & aEnvironment,int aStackTop)1747 void LispCustomEvalLocals(LispEnvironment& aEnvironment, int aStackTop)
1748 {
1749 aEnvironment.CurrentLocals(RESULT);
1750 }
1751
LispCustomEvalStop(LispEnvironment & aEnvironment,int aStackTop)1752 void LispCustomEvalStop(LispEnvironment& aEnvironment, int aStackTop)
1753 {
1754 if (!aEnvironment.iDebugger)
1755 throw LispErrGeneric(
1756 "Trying to get CustomEval results while not in custom evaluation");
1757
1758 aEnvironment.iDebugger->iStopped = true;
1759
1760 InternalTrue(aEnvironment, RESULT);
1761 }
1762
LispTraceStack(LispEnvironment & aEnvironment,int aStackTop)1763 void LispTraceStack(LispEnvironment& aEnvironment, int aStackTop)
1764 {
1765 LispLocalEvaluator local(aEnvironment, new TracedStackEvaluator);
1766 InternalEval(aEnvironment, RESULT, ARGUMENT(1));
1767 }
1768
LispReadLisp(LispEnvironment & aEnvironment,int aStackTop)1769 void LispReadLisp(LispEnvironment& aEnvironment, int aStackTop)
1770 {
1771 LispTokenizer& tok = *aEnvironment.iCurrentTokenizer;
1772 LispParser parser(tok, *aEnvironment.CurrentInput(), aEnvironment);
1773 // Read expression
1774 parser.Parse(RESULT);
1775 }
1776
LispReadLispListed(LispEnvironment & aEnvironment,int aStackTop)1777 void LispReadLispListed(LispEnvironment& aEnvironment, int aStackTop)
1778 {
1779 LispTokenizer& tok = *aEnvironment.iCurrentTokenizer;
1780 LispParser parser(tok, *aEnvironment.CurrentInput(), aEnvironment);
1781 parser.iListed = true;
1782 // Read expression
1783 parser.Parse(RESULT);
1784 }
1785
LispTraceRule(LispEnvironment & aEnvironment,int aStackTop)1786 void LispTraceRule(LispEnvironment& aEnvironment, int aStackTop)
1787 {
1788 LispPtr* ptr = ARGUMENT(0)->Nixed()->SubList();
1789 LispUserFunction* userfunc = nullptr;
1790 if (ptr)
1791 userfunc = GetUserFunction(aEnvironment, ptr);
1792 LispLocalTrace trace(userfunc);
1793 InternalEval(aEnvironment, RESULT, ARGUMENT(2));
1794 }
1795
LispType(LispEnvironment & aEnvironment,int aStackTop)1796 void LispType(LispEnvironment& aEnvironment, int aStackTop)
1797 {
1798 LispPtr evaluated(ARGUMENT(1));
1799 LispPtr* subList = evaluated->SubList();
1800 LispObject* head = nullptr;
1801 if (!subList) {
1802 goto EMPTY;
1803 }
1804 head = (*subList);
1805 if (!head->String())
1806 goto EMPTY;
1807 RESULT = LispAtom::New(
1808 aEnvironment,
1809 *aEnvironment.HashTable().LookUp(stringify(*head->String())));
1810 return;
1811
1812 EMPTY:
1813 RESULT = LispAtom::New(aEnvironment, "\"\"");
1814 return;
1815 }
1816
YacasStringMidGet(LispEnvironment & aEnvironment,int aStackTop)1817 void YacasStringMidGet(LispEnvironment& aEnvironment, int aStackTop)
1818 {
1819 CheckArgIsString(3, aEnvironment, aStackTop);
1820 LispPtr evaluated(ARGUMENT(3));
1821
1822 const LispString* orig = evaluated->String();
1823
1824 LispPtr index(ARGUMENT(1));
1825 CheckArg(index, 1, aEnvironment, aStackTop);
1826 CheckArg(index->String(), 1, aEnvironment, aStackTop);
1827 const int sfrom = InternalAsciiToInt(*index->String());
1828 CheckArg(sfrom > 0, 1, aEnvironment, aStackTop);
1829 const std::size_t from = sfrom;
1830
1831 index = (ARGUMENT(2));
1832 CheckArg(index, 2, aEnvironment, aStackTop);
1833 CheckArg(index->String(), 2, aEnvironment, aStackTop);
1834 const int scount = InternalAsciiToInt(*index->String());
1835 const std::size_t count = scount;
1836
1837 std::string str = "\"";
1838 // FIXME: it's actually the set of args which is wrong, not the specific one
1839 CheckArg(from + count < orig->size(), 1, aEnvironment, aStackTop);
1840 for (std::size_t i = from; i < from + count; ++i)
1841 str.push_back((*orig)[i]);
1842 str.push_back('\"');
1843 RESULT = LispAtom::New(aEnvironment, str);
1844 }
1845
YacasStringMidSet(LispEnvironment & aEnvironment,int aStackTop)1846 void YacasStringMidSet(LispEnvironment& aEnvironment, int aStackTop)
1847 {
1848 CheckArgIsString(3, aEnvironment, aStackTop);
1849 LispPtr evaluated(ARGUMENT(3));
1850 const LispString* orig = evaluated->String();
1851 LispPtr index(ARGUMENT(1));
1852 CheckArg(index, 1, aEnvironment, aStackTop);
1853 CheckArg(index->String(), 1, aEnvironment, aStackTop);
1854 const int sfrom = InternalAsciiToInt(*index->String());
1855 CheckArg(sfrom > 0, 1, aEnvironment, aStackTop);
1856 const std::size_t from = sfrom;
1857
1858 LispPtr ev2(ARGUMENT(2));
1859 CheckArgIsString(2, aEnvironment, aStackTop);
1860 const LispString* replace = ev2->String();
1861
1862 std::string str(*orig);
1863 const std::size_t count = replace->size();
1864 // FIXME: it's actually the set of args which is wrong, not the specific one
1865 CheckArg(from + count < orig->size() + 2, 1, aEnvironment, aStackTop);
1866
1867 for (std::size_t i = 0; i < count - 2; ++i)
1868 str[i + from] = (*replace)[i + 1];
1869 RESULT = LispAtom::New(aEnvironment, str);
1870 }
1871
LispFindFunction(LispEnvironment & aEnvironment,int aStackTop)1872 void LispFindFunction(LispEnvironment& aEnvironment, int aStackTop)
1873 {
1874 CheckSecure(aEnvironment, aStackTop);
1875
1876 LispPtr evaluated(ARGUMENT(1));
1877
1878 // Get file name
1879 CheckArg(evaluated, 1, aEnvironment, aStackTop);
1880 const LispString* orig = evaluated->String();
1881 CheckArg(orig, 1, aEnvironment, aStackTop);
1882 const std::string oper = InternalUnstringify(*orig);
1883
1884 LispMultiUserFunction* multiUserFunc =
1885 aEnvironment.MultiUserFunction(aEnvironment.HashTable().LookUp(oper));
1886 if (multiUserFunc) {
1887 LispDefFile* def = multiUserFunc->iFileToOpen;
1888 if (def) {
1889 RESULT = LispAtom::New(aEnvironment, def->FileName());
1890 return;
1891 }
1892 }
1893
1894 RESULT = LispAtom::New(aEnvironment, "\"\"");
1895 }
1896
1897 /// Corresponds to the Yacas function \c PatternCreate .
1898 /// This function constructs a new PatternClass, and puts it in a new
1899 /// LispGenericObject. The result is set to this LispGenericObject.
GenPatternCreate(LispEnvironment & aEnvironment,int aStackTop)1900 void GenPatternCreate(LispEnvironment& aEnvironment, int aStackTop)
1901 {
1902 LispPtr pattern(ARGUMENT(1));
1903 LispPtr postpredicate(ARGUMENT(2));
1904
1905 LispIterator iter(pattern);
1906 LispObject* pObj = iter.getObj();
1907 CheckArg(pObj, 1, aEnvironment, aStackTop);
1908 LispPtr* pPtr = pObj->SubList();
1909 CheckArg(pPtr, 1, aEnvironment, aStackTop);
1910 iter = *pPtr;
1911 CheckArg(iter.getObj(), 1, aEnvironment, aStackTop);
1912 ++iter;
1913
1914 YacasPatternPredicateBase* matcher =
1915 new YacasPatternPredicateBase(aEnvironment, *iter, postpredicate);
1916 PatternClass* p = new PatternClass(matcher);
1917 RESULT = (LispGenericClass::New(p));
1918 }
1919
GenPatternMatches(LispEnvironment & aEnvironment,int aStackTop)1920 void GenPatternMatches(LispEnvironment& aEnvironment, int aStackTop)
1921 {
1922 LispPtr pattern(ARGUMENT(1));
1923 GenericClass* gen = pattern->Generic();
1924 PatternClass* pat = dynamic_cast<PatternClass*>(gen);
1925 CheckArg(pat, 1, aEnvironment, aStackTop);
1926
1927 LispPtr list(ARGUMENT(2));
1928
1929 LispIterator iter(list);
1930 LispObject* pObj = iter.getObj();
1931 CheckArg(pObj, 2, aEnvironment, aStackTop);
1932 LispPtr* pPtr = pObj->SubList();
1933 CheckArg(pPtr, 2, aEnvironment, aStackTop);
1934 iter = *pPtr;
1935 CheckArg(iter.getObj(), 2, aEnvironment, aStackTop);
1936 ++iter;
1937
1938 CheckArg(iter.getObj(), 2, aEnvironment, aStackTop);
1939 bool matches = pat->Matches(aEnvironment, *iter);
1940 InternalBoolean(aEnvironment, RESULT, matches);
1941 }
1942
LispRuleBaseDefined(LispEnvironment & aEnvironment,int aStackTop)1943 void LispRuleBaseDefined(LispEnvironment& aEnvironment, int aStackTop)
1944 {
1945 LispPtr name(ARGUMENT(1));
1946 const LispString* orig = name->String();
1947 CheckArg(orig, 1, aEnvironment, aStackTop);
1948 const std::string oper = InternalUnstringify(*orig);
1949
1950 LispPtr sizearg(ARGUMENT(2));
1951 CheckArg(sizearg, 2, aEnvironment, aStackTop);
1952 CheckArg(sizearg->String(), 2, aEnvironment, aStackTop);
1953
1954 int arity = InternalAsciiToInt(*sizearg->String());
1955
1956 LispUserFunction* userFunc =
1957 aEnvironment.UserFunction(aEnvironment.HashTable().LookUp(oper), arity);
1958 InternalBoolean(aEnvironment, RESULT, !!userFunc);
1959 }
1960
LispDefLoadFunction(LispEnvironment & aEnvironment,int aStackTop)1961 void LispDefLoadFunction(LispEnvironment& aEnvironment, int aStackTop)
1962 {
1963 LispPtr name(ARGUMENT(1));
1964 const LispString* orig = name->String();
1965 CheckArg(orig, 1, aEnvironment, aStackTop);
1966 const std::string oper = InternalUnstringify(*orig);
1967
1968 LispMultiUserFunction* multiUserFunc =
1969 aEnvironment.MultiUserFunction(aEnvironment.HashTable().LookUp(oper));
1970 if (multiUserFunc) {
1971 if (multiUserFunc->iFileToOpen != nullptr) {
1972 LispDefFile* def = multiUserFunc->iFileToOpen;
1973 if (!def->IsLoaded()) {
1974 multiUserFunc->iFileToOpen = nullptr;
1975 // InternalUse(aEnvironment, def->FileName());
1976 }
1977 }
1978 }
1979 InternalTrue(aEnvironment, RESULT);
1980 }
1981
LispRuleBaseArgList(LispEnvironment & aEnvironment,int aStackTop)1982 void LispRuleBaseArgList(LispEnvironment& aEnvironment, int aStackTop)
1983 {
1984 LispPtr name(ARGUMENT(1));
1985 const LispString* orig = name->String();
1986 CheckArg(orig, 1, aEnvironment, aStackTop);
1987 const std::string oper = InternalUnstringify(*orig);
1988
1989 LispPtr sizearg(ARGUMENT(2));
1990 CheckArg(sizearg, 2, aEnvironment, aStackTop);
1991 CheckArg(sizearg->String(), 2, aEnvironment, aStackTop);
1992
1993 int arity = InternalAsciiToInt(*sizearg->String());
1994
1995 LispUserFunction* userFunc =
1996 aEnvironment.UserFunction(aEnvironment.HashTable().LookUp(oper), arity);
1997 CheckArg(userFunc, 1, aEnvironment, aStackTop);
1998
1999 const LispPtr& list = userFunc->ArgList();
2000 LispPtr head(aEnvironment.iList->Copy());
2001 head->Nixed() = (list);
2002 RESULT = (LispSubList::New(head));
2003 }
2004
InternalNewRulePattern(LispEnvironment & aEnvironment,int aStackTop,bool aMacroMode)2005 static void InternalNewRulePattern(LispEnvironment& aEnvironment,
2006 int aStackTop,
2007 bool aMacroMode)
2008 {
2009 int arity;
2010 int precedence;
2011
2012 LispPtr ar;
2013 LispPtr pr;
2014 LispPtr predicate;
2015 LispPtr body;
2016
2017 // Get operator
2018 CheckArg(ARGUMENT(1), 1, aEnvironment, aStackTop);
2019 const LispString* orig = ARGUMENT(1)->String();
2020 CheckArg(orig, 1, aEnvironment, aStackTop);
2021 ar = (ARGUMENT(2));
2022 pr = (ARGUMENT(3));
2023 predicate = (ARGUMENT(4));
2024 body = (ARGUMENT(5));
2025
2026 // The arity
2027 CheckArg(ar, 2, aEnvironment, aStackTop);
2028 CheckArg(ar->String(), 2, aEnvironment, aStackTop);
2029 arity = InternalAsciiToInt(*ar->String());
2030
2031 // The precedence
2032 CheckArg(ar, 3, aEnvironment, aStackTop);
2033 CheckArg(ar->String(), 3, aEnvironment, aStackTop);
2034 precedence = InternalAsciiToInt(*pr->String());
2035
2036 // Finally define the rule base
2037 aEnvironment.DefineRulePattern(
2038 SymbolName(aEnvironment, *orig), arity, precedence, predicate, body);
2039
2040 // Return true
2041 InternalTrue(aEnvironment, RESULT);
2042 }
2043
LispNewRulePattern(LispEnvironment & aEnvironment,int aStackTop)2044 void LispNewRulePattern(LispEnvironment& aEnvironment, int aStackTop)
2045 {
2046 InternalNewRulePattern(aEnvironment, aStackTop, false);
2047 }
2048
LispMacroNewRulePattern(LispEnvironment & aEnvironment,int aStackTop)2049 void LispMacroNewRulePattern(LispEnvironment& aEnvironment, int aStackTop)
2050 {
2051 InternalNewRulePattern(aEnvironment, aStackTop, true);
2052 }
2053