Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4680 right-hear 1
/** \file lispenvironment.h
2
 *  General environment access.
3
 *
4
 */
5
 
6
 
7
#ifndef __lispenvironment_h__
8
#define __lispenvironment_h__
9
 
10
#include "yacasbase.h"
11
#include "lispobject.h"
12
#include "lisphash.h"
13
#include "lispevalhash.h"
14
#include "lispcleanupstack.h"
15
#include "deffile.h"
16
#include "lispio.h"
17
#include "stringio.h"
18
#include "lispglobals.h"
19
#include "xmltokenizer.h"
20
#include "errors.h"
21
 
22
class CCompressedArchive; /* defined in archiver.h */
23
 
24
class LispDefFiles;
25
class InputDirectories : public CDeletingArrayGrower >
26
{
27
};
28
 
29
class LispInput;
30
class LispOutput;
31
class LispPrinter;
32
class LispOperators;
33
class LispUserFunctions;
34
class LispUserFunction;
35
class LispMultiUserFunction;
36
class LispEvaluatorBase;
37
class BasicEvaluator;
38
class DefaultDebugger;
39
class LispEnvironment;
40
 
41
 
42
/// The Lisp environment.
43
/// This huge class is the central class of the Yacas program. It
44
/// implements a dialect of Lisp.
45
 
46
class LispEnvironment : public YacasBase
47
{
48
public:
49
  /// \name Constructor and destructor
50
  //@{
51
  LispEnvironment(YacasCoreCommands &aCoreCommands,
52
                  LispUserFunctions& aUserFunctions,
53
                  LispGlobal& aGlobals,
54
                  LispHashTable& aHashTable,
55
                  LispOutput* aOutput,
56
                  LispPrinter& aPrinter,
57
                  LispOperators &aPreFixOperators,
58
                  LispOperators &aInFixOperators,
59
                  LispOperators &aPostFixOperators,
60
                  LispOperators &aBodiedOperators,
61
                  LispInput*    aCurrentInput,
62
                  LispInt aStackSize);
63
  ~LispEnvironment();
64
  //@}
65
 
66
public:
67
  /// \name Lisp variables
68
  //@{
69
 
70
  /// Assign a value to a Lisp variable.
71
  /// \param aString name of the variable
72
  /// \param aValue value to be assigned to \a aString
73
  ///
74
  /// If there is a local variable with the name \a aString, the
75
  /// object \a aValue is assigned to it. Otherwise, a
76
  /// LispGlobalVariable is constructed, and it is associated with
77
  /// \a aValue in #iGlobals.
78
  /// \sa FindLocal
79
  void SetVariable(LispString * aString, LispPtr& aValue, LispBoolean aGlobalLazyVariable);
80
 
81
  /// In debug mode, DebugModeVerifySettingGlobalVariables raises a warning if a global variable is set.
82
  void DebugModeVerifySettingGlobalVariables(LispPtr & aVariable, LispBoolean aGlobalLazyVariable);
83
 
84
  /// Get the value assigned to a variable.
85
  /// \param aVariable name of the variable
86
  /// \param aResult (on exit) value of \a aVariable
87
  ///
88
  /// - If there is a local variable with the name \a aString,
89
  ///   \a aResult is set to point to the value assigned to this local
90
  ///   variable.
91
  /// - If there is a global variable \a aString and its
92
  ///   #iEvalBeforeReturn is false, its value is returned via
93
  ///   \a aResult.
94
  /// - If there is a global variable \a aString and its
95
  ///   #iEvalBeforeReturn is true, its value is evaluated. The
96
  ///   result is assigned back to the variable, its
97
  ///   #iEvalBeforeReturn is set to false, and a copy of the result
98
  ///   is returned in \a aResult.
99
  /// - Otherwise, \a aResult is set to #NULL.
100
  void GetVariable(LispString * aVariable,LispPtr& aResult);
101
 
102
  void UnsetVariable(LispString * aString);
103
  void PushLocalFrame(LispBoolean aFenced);
104
  void PopLocalFrame();
105
  void NewLocal(LispString * aVariable,LispObject* aValue);
106
  void CurrentLocals(LispPtr& aResult);
107
  //@}
108
 
109
public:
110
  /// \name Lisp functions
111
  //@{
112
 
113
  /// Return the #iCoreCommands attribute.
114
  inline YacasCoreCommands& CoreCommands();
115
 
116
  /// Add a command to the list of core commands.
117
  /// \param aEvaluatorFunc C function evaluating the core command
118
  /// \param aString name of the command
119
  /// \param aNrArgs number of arguments
120
  /// \param aFlags flags, see YacasEvaluator::FunctionFlags
121
  void SetCommand(YacasEvalCaller aEvaluatorFunc, LispChar * aString,LispInt aNrArgs,LispInt aFlags);
122
 
123
  void RemoveCommand(LispChar * aString);
124
  void RemoveCoreCommand(LispChar * aString);
125
 
126
  inline  LispHashTable& HashTable();
127
  LispUserFunction* UserFunction(LispPtr& aArguments);
128
  LispUserFunction* UserFunction(LispString * aName,LispInt aArity);
129
 
130
  /// Return LispMultiUserFunction with given name.
131
  /// \param aArguments name of the multi user function
132
  ///
133
  /// The table of user functions, #iUserFunctions, is consulted. If
134
  /// a user function with the given name exists, it is returned.
135
  /// Otherwise, a new LispMultiUserFunction is constructed, added
136
  /// to #iUserFunctions, and returned.
137
  LispMultiUserFunction* MultiUserFunction(LispString * aArguments);
138
 
139
  LispDefFiles& DefFiles();
140
  void DeclareRuleBase(LispString * aOperator, LispPtr& aParameters,
141
                       LispInt aListed);
142
  void DeclareMacroRuleBase(LispString * aOperator, LispPtr& aParameters,
143
                       LispInt aListed);
144
  void DefineRule(LispString * aOperator,LispInt aArity,
145
                          LispInt aPrecedence, LispPtr& aPredicate,
146
                          LispPtr& aBody);
147
  void DefineRulePattern(LispString * aOperator,LispInt aArity,
148
                          LispInt aPrecedence, LispPtr& aPredicate,
149
                          LispPtr& aBody);
150
 
151
 
152
  void UnFenceRule(LispString * aOperator,LispInt aArity);
153
  void Retract(LispString * aOperator,LispInt aArity);
154
  void HoldArgument(LispString *  aOperator,LispString * aVariable);
155
  //@}
156
 
157
  LispString * FindCachedFile(LispChar * aFileName);
158
 
159
public:
160
  /// \name Precision
161
  //@{
162
 
163
  /// set precision to a given number of decimal digits
164
  void SetPrecision(LispInt aPrecision);
165
  inline LispInt Precision(void) const;
166
  inline LispInt BinaryPrecision(void) const;
167
  //@}
168
 
169
public:
170
  inline void SetPrettyPrinter(LispString * aPrettyPrinter);
171
  inline LispString * PrettyPrinter(void);
172
 
173
  inline void SetPrettyReader(LispString * aPrettyReader);
174
  inline LispString * PrettyReader(void);
175
 
176
public:
177
  LispInt GetUniqueId();
178
public:
179
  LispPrinter& CurrentPrinter();
180
 
181
public:
182
  /// \name Operators
183
  //@{
184
  LispOperators& PreFix();
185
  LispOperators& InFix();
186
  LispOperators& PostFix();
187
  LispOperators& Bodied();
188
  //@}
189
 
190
public:
191
  /// \name Input and output
192
  //@{
193
  LispInput* CurrentInput();
194
  void SetCurrentInput(LispInput* aInput);
195
public:
196
  LispOutput* CurrentOutput();
197
  void SetCurrentOutput(LispOutput* aOutput);
198
public:
199
  void SetUserError(LispChar * aErrorString);
200
  LispChar * ErrorString(LispInt aError);
201
  //@}
202
 
203
protected:
204
  /// current precision for user interaction, in decimal and in binary
205
  LispInt iPrecision;
206
  LispInt iBinaryPrecision;
207
public:
208
  InputDirectories iInputDirectories;
209
  DeletingLispCleanup iCleanup;
210
  LispInt iEvalDepth;
211
  LispInt iMaxEvalDepth;
212
  CCompressedArchive *iArchive;
213
  LispEvaluatorBase* iEvaluator;
214
 
215
public: // Error information when some error occurs.
216
  InputStatus iInputStatus;
217
  LispInt iSecure;
218
public: // pre-found
219
  RefPtr iTrue;
220
  RefPtr iFalse;
221
 
222
  RefPtr iEndOfFile;
223
  RefPtr iEndStatement;
224
  RefPtr iProgOpen;
225
  RefPtr iProgClose;
226
  RefPtr iNth;
227
  RefPtr iBracketOpen;
228
  RefPtr iBracketClose;
229
  RefPtr iListOpen;
230
  RefPtr iListClose;
231
  RefPtr iComma;
232
  RefPtr iList;
233
  RefPtr iProg;
234
 
235
  LispInt iLastUniqueId;
236
 
237
public: // Error reporting
238
  LispString iError;
239
  StringOutput iErrorOutput;
240
  DefaultDebugger* iDebugger;
241
 
242
private:
243
  LispPtr *FindLocal(LispString * aVariable);
244
 
245
private:
246
 
247
  class LispLocalVariable : public YacasBase
248
  {
249
  public:
250
    LispLocalVariable(LispString * aVariable,
251
                      LispObject* aValue)
252
      : iNext(NULL), iVariable(aVariable),iValue(aValue)
253
    {
254
      ++aVariable->iReferenceCount;
255
    };
256
    ~LispLocalVariable()
257
    {
258
      --iVariable->iReferenceCount;
259
    }
260
  private:
261
    LispLocalVariable(const LispLocalVariable& aOther) : iNext(NULL), iVariable(NULL),iValue(NULL)
262
    {
263
      // copy constructor not written yet, hence the assert
264
      LISPASSERT(0);
265
    }
266
    LispLocalVariable& operator=(const LispLocalVariable& aOther)
267
    {
268
      // copy constructor not written yet, hence the assert
269
      LISPASSERT(0);
270
      return *this;
271
    }
272
 
273
  public:
274
    LispLocalVariable* iNext;
275
    LispString * iVariable;
276
    LispPtr iValue;
277
  };
278
  class LocalVariableFrame : public YacasBase
279
  {
280
  public:
281
    LocalVariableFrame(LocalVariableFrame *aNext,
282
                       LispLocalVariable* aFirst)
283
        : iNext(aNext), iFirst(aFirst), iLast(aFirst) { }
284
    void Add(LispLocalVariable* aNew)
285
    {
286
      aNew->iNext = iFirst;
287
      iFirst = aNew;
288
    }
289
    ~LocalVariableFrame()
290
    {
291
      LispLocalVariable* t = iFirst;
292
      LispLocalVariable* next;
293
      while (t != iLast)
294
      {
295
        next = t->iNext;
296
        delete t;
297
        t = next;
298
      }
299
    }
300
 
301
  private:
302
    LocalVariableFrame(const LocalVariableFrame& aOther) : iNext(NULL),iFirst(NULL),iLast(NULL)
303
    {
304
      // copy constructor not written yet, hence the assert
305
      LISPASSERT(0);
306
    }
307
    LocalVariableFrame& operator=(const LocalVariableFrame& aOther)
308
    {
309
      // copy constructor not written yet, hence the assert
310
      LISPASSERT(0);
311
      return *this;
312
    }
313
  public:
314
    LocalVariableFrame *iNext;
315
    LispLocalVariable* iFirst;
316
    LispLocalVariable* iLast;
317
  };
318
public: //Well... only because I want to be able to show the stack to the outside world...
319
  LocalVariableFrame *iLocalsList;
320
  LispOutput*    iInitialOutput;
321
private:
322
 
323
  /// Hash of core commands with associated YacasEvaluator
324
  YacasCoreCommands& iCoreCommands;
325
 
326
  LispUserFunctions& iUserFunctions;
327
  LispHashTable& iHashTable;
328
  LispDefFiles   iDefFiles;
329
  LispPrinter&   iPrinter;
330
  LispOutput*    iCurrentOutput;
331
 
332
  /// Hash of global variables with their values
333
  LispGlobal&    iGlobals;
334
 
335
  LispOperators& iPreFixOperators;
336
  LispOperators& iInFixOperators;
337
  LispOperators& iPostFixOperators;
338
  LispOperators& iBodiedOperators;
339
 
340
  LispInput* iCurrentInput;
341
 
342
  LispChar * theUserError;
343
 
344
  LispString * iPrettyReader;
345
  LispString * iPrettyPrinter;
346
public:
347
  LispTokenizer iDefaultTokenizer;
348
  CommonLispTokenizer iCommonLispTokenizer;
349
  XmlTokenizer  iXmlTokenizer;
350
  LispTokenizer* iCurrentTokenizer;
351
 
352
public:
353
  /** YacasArgStack implements a stack of pointers to objects that can be used to pass
354
  *  arguments to functions, and receive results back.
355
  */
356
  class YacasArgStack
357
  {
358
  public:
359
    YacasArgStack(LispInt aStackSize) : iStack(),iStackCnt(0)
360
    {
361
      iStack.ResizeTo( aStackSize );
362
    }
363
    inline LispInt GetStackTop() const {return iStackCnt;}
364
    inline void RaiseStackOverflowError() const
365
    {
366
      RaiseError("Argument stack reached maximum. Please extend argument stack with --stack argument on the command line.");
367
    }
368
    inline void PushArgOnStack(LispObject* aObject)
369
    {
370
      if (iStackCnt >= iStack.Size())
371
      {
372
        RaiseStackOverflowError();
373
      }
374
      //LISPASSERT(iStackCnt>=0 /*&& iStackCnt
375
      iStack[iStackCnt] = (aObject);
376
      iStackCnt++;
377
    }
378
    inline void PushNulls(LispInt aNr)
379
    {
380
      LispInt aStackCnt = iStackCnt + aNr;
381
      if (aStackCnt > iStack.Size() || aStackCnt < 0)
382
      {
383
        RaiseStackOverflowError();
384
      }
385
      iStackCnt = aStackCnt;
386
    }
387
    inline LispPtr& GetElement(LispInt aPos)
388
    {
389
      LISPASSERT(0<=aPos && aPos
390
      //LISPASSERT(aPos>=0 && aPos
391
      return iStack[aPos];
392
    }
393
    inline void PopTo(LispInt aTop)
394
    {
395
      LISPASSERT(0<=aTop && aTop<=iStackCnt);
396
      while (iStackCnt>aTop)
397
      {
398
        iStackCnt--;
399
        iStack[iStackCnt] = (NULL);
400
      }
401
    }
402
  protected:
403
    // Invariants:
404
    //    0 <= iStackCnt <= iStack.Size()
405
    //    iStack[iStackCnt..iStack.Size()-1] = NULL
406
    LispPtrArray iStack;
407
    LispInt iStackCnt;    // number of items on the stack
408
  };
409
  YacasArgStack iStack;
410
 
411
private:
412
 
413
  inline LispEnvironment(const LispEnvironment& aOther)
414
    :
415
    iPrecision(0),  // default user precision of 10 decimal digits
416
    iBinaryPrecision(0),  // same as 34 bits
417
    iInputDirectories(),
418
    iCleanup(),
419
    iEvalDepth(0),
420
    iMaxEvalDepth(0),
421
    iArchive(NULL),
422
    iEvaluator(NULL),
423
    iInputStatus(),
424
    iSecure(0),
425
    iTrue(),
426
    iFalse(),
427
    iEndOfFile(),
428
    iEndStatement(),
429
    iProgOpen(),
430
    iProgClose(),
431
    iNth(),
432
    iBracketOpen(),
433
    iBracketClose(),
434
    iListOpen(),
435
    iListClose(),
436
    iComma(),
437
    iList(),
438
    iProg(),
439
    iLastUniqueId(0),
440
    iError(),
441
    iErrorOutput(aOther.iErrorOutput),
442
    iDebugger(NULL),
443
    iLocalsList(NULL),
444
    iInitialOutput(aOther.iInitialOutput),
445
    iCoreCommands(aOther.iCoreCommands),
446
    iUserFunctions(aOther.iUserFunctions),
447
    iHashTable(aOther.iHashTable),
448
    iDefFiles(),
449
    iPrinter(aOther.iPrinter),
450
    iCurrentOutput(aOther.iCurrentOutput),
451
    iGlobals(aOther.iGlobals),
452
    iPreFixOperators(aOther.iPreFixOperators),
453
    iInFixOperators(aOther.iInFixOperators),
454
    iPostFixOperators(aOther.iPostFixOperators),
455
    iBodiedOperators(aOther.iBodiedOperators),
456
    iCurrentInput(aOther.iCurrentInput),
457
    theUserError(NULL),
458
    iPrettyReader(NULL),
459
    iPrettyPrinter(NULL),
460
    iDefaultTokenizer(),
461
    iCommonLispTokenizer(),
462
    iXmlTokenizer(),
463
    iCurrentTokenizer(NULL),
464
    iStack(0)
465
  {
466
    // copy constructor has not been made yet, hence the assert
467
    LISPASSERT(0);
468
  }
469
  LispEnvironment& operator=(const LispEnvironment& aOther)
470
  {
471
    // copy constructor has not been made yet, hence the assert
472
    LISPASSERT(0);
473
    return *this;
474
  }
475
 
476
};
477
 
478
inline LispInt LispEnvironment::Precision(void) const
479
{
480
    return iPrecision;
481
}
482
 
483
inline LispInt LispEnvironment::BinaryPrecision(void) const
484
{
485
  return iBinaryPrecision;
486
}
487
 
488
 
489
 
490
inline YacasCoreCommands& LispEnvironment::CoreCommands()
491
{
492
    return iCoreCommands;
493
}
494
 
495
 
496
inline LispHashTable& LispEnvironment::HashTable()
497
{
498
    return iHashTable;
499
}
500
 
501
 
502
 
503
// Local lisp stack, unwindable by the exception handler
504
class LispLocalFrame : public LispBase
505
{
506
public:
507
    LispLocalFrame(LispEnvironment& aEnvironment, LispBoolean aFenced)
508
        : iEnvironment(aEnvironment)
509
    {
510
        iEnvironment.PushLocalFrame(aFenced);
511
        SAFEPUSH(iEnvironment,*this);
512
    };
513
    virtual ~LispLocalFrame()
514
    {
515
        SAFEPOP(iEnvironment);
516
        Delete();
517
    };
518
    virtual void Delete();
519
private:
520
    LispEnvironment& iEnvironment;
521
};
522
 
523
 
524
 
525
class LispSecureFrame : public LispBase
526
{
527
public:
528
  LispSecureFrame(LispEnvironment& aEnvironment)
529
      : iEnvironment(aEnvironment),iPreviousSecure(aEnvironment.iSecure)
530
  {
531
    iEnvironment.iSecure = 1;
532
    SAFEPUSH(iEnvironment,*this);
533
  };
534
  virtual ~LispSecureFrame()
535
  {
536
    SAFEPOP(iEnvironment);
537
    Delete();
538
  };
539
  virtual void Delete();
540
private:
541
  LispEnvironment& iEnvironment;
542
  LispInt iPreviousSecure;
543
};
544
 
545
 
546
// LispLocalInput takes ownership over the LispInput class
547
class LispLocalInput : public LispBase
548
{
549
public:
550
  LispLocalInput(LispEnvironment& aEnvironment, LispInput* aInput)
551
      : iEnvironment(aEnvironment),iPreviousInput(iEnvironment.CurrentInput())
552
  {
553
    iEnvironment.SetCurrentInput(aInput);
554
    SAFEPUSH(iEnvironment,*this);
555
  };
556
  virtual ~LispLocalInput()
557
  {
558
    SAFEPOP(iEnvironment);
559
    Delete();
560
  };
561
  virtual void Delete();
562
private:
563
  LispLocalInput(const LispLocalInput& aOther): iEnvironment(aOther.iEnvironment),iPreviousInput(iEnvironment.CurrentInput())
564
  {
565
    // copy constructor not written yet, hence the assert
566
    LISPASSERT(0);
567
  };
568
  LispLocalInput& operator=(const LispLocalInput& aOther)
569
  {
570
    // copy constructor not written yet, hence the assert
571
    LISPASSERT(0);
572
    return *this;
573
  };
574
 
575
private:
576
  LispEnvironment& iEnvironment;
577
  LispInput* iPreviousInput;
578
};
579
 
580
 
581
// LispLocalInput takes ownership over the LispInput class
582
class LispLocalOutput : public LispBase
583
{
584
public:
585
  LispLocalOutput(LispEnvironment& aEnvironment, LispOutput* aOutput)
586
      : iEnvironment(aEnvironment), iPreviousOutput(iEnvironment.CurrentOutput())
587
  {
588
    iPreviousOutput = iEnvironment.CurrentOutput();
589
    iEnvironment.SetCurrentOutput(aOutput);
590
    SAFEPUSH(iEnvironment,*this);
591
  };
592
  virtual ~LispLocalOutput()
593
  {
594
    SAFEPOP(iEnvironment);
595
    Delete();
596
  };
597
  virtual void Delete();
598
private:
599
  LispLocalOutput(const LispLocalOutput& aOther): iEnvironment(aOther.iEnvironment), iPreviousOutput(iEnvironment.CurrentOutput())
600
  {
601
    // copy constructor not written yet, hence the assert
602
    LISPASSERT(0);
603
  }
604
  LispLocalOutput& operator=(const LispLocalOutput& aOther)
605
  {
606
    // copy constructor not written yet, hence the assert
607
    LISPASSERT(0);
608
    return *this;
609
  }
610
private:
611
  LispEnvironment& iEnvironment;
612
  LispOutput* iPreviousOutput;
613
};
614
 
615
 
616
class LispLocalEvaluator : public YacasBase
617
{
618
public:
619
  LispLocalEvaluator(LispEnvironment& aEnvironment,LispEvaluatorBase* aNewEvaluator);
620
  ~LispLocalEvaluator();
621
 
622
private:
623
  LispLocalEvaluator(const LispLocalEvaluator& aOther) : iPreviousEvaluator(NULL), iEnvironment(aOther.iEnvironment)
624
  {
625
    // copy constructor not written yet, hence the assert
626
    LISPASSERT(0);
627
  }
628
  LispLocalEvaluator& operator=(const LispLocalEvaluator& aOther)
629
  {
630
    // copy constructor not written yet, hence the assert
631
    LISPASSERT(0);
632
    return *this;
633
  }
634
 
635
private:
636
  LispEvaluatorBase* iPreviousEvaluator;
637
  LispEnvironment& iEnvironment;
638
};
639
 
640
class LispLocalTrace : public YacasBase
641
{
642
public:
643
  LispLocalTrace(LispUserFunction* aUserFunc);
644
  ~LispLocalTrace();
645
private:
646
  LispLocalTrace(const LispLocalTrace& aOther) : iUserFunc(NULL)
647
  {
648
    // copy constructor not written yet, hence the assert
649
    LISPASSERT(0);
650
  }
651
  LispLocalTrace& operator=(const LispLocalTrace& aOther)
652
  {
653
    // copy constructor not written yet, hence the assert
654
    LISPASSERT(0);
655
    return *this;
656
  }
657
private:
658
  LispUserFunction* iUserFunc;
659
};
660
 
661
class LocalArgs : public YacasBase
662
{
663
public:
664
  LocalArgs(LispPtr* aPtrs) : iPtrs(aPtrs) {};
665
  ~LocalArgs()
666
  {
667
    if (iPtrs)
668
      delete[] iPtrs;
669
  }
670
private:
671
  LocalArgs(const LocalArgs& aOther) : iPtrs(NULL)
672
  {
673
    // copy constructor not written yet, hence the assert
674
    LISPASSERT(0);
675
  }
676
  LocalArgs& operator=(const LocalArgs& aOther)
677
  {
678
    // copy constructor not written yet, hence the assert
679
    LISPASSERT(0);
680
    return *this;
681
  }
682
private:
683
  LispPtr* iPtrs;
684
};
685
 
686
 
687
 
688
inline void LispEnvironment::SetPrettyReader(LispString * aPrettyReader)
689
{
690
  iPrettyReader = aPrettyReader;
691
}
692
inline LispString * LispEnvironment::PrettyReader(void)
693
{
694
  return iPrettyReader;
695
}
696
 
697
inline void LispEnvironment::SetPrettyPrinter(LispString * aPrettyPrinter)
698
{
699
  iPrettyPrinter = aPrettyPrinter;
700
}
701
inline LispString * LispEnvironment::PrettyPrinter(void)
702
{
703
  return iPrettyPrinter;
704
}
705
 
706
 
707
#endif
708
 
709