I do a fort compiler in C ++ , faced with the problem of implementing a common for int and char[] stack. Tell me how best to implement a common stack?
|
1 answer
There are at least two options:
C-approach:
typedef struct ForthType { enum { INT; FLOAT; PTR; STR; BYTECODE; ... } type; // ΡΡΠ³ ΡΠΈΠΏΠ° union { // Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅, Π² ΠΏΠ°ΠΌΡΡΠΈ ΠΏΠ΅ΡΠ΅ΠΊΡΡΠ²Π°ΡΡΡΡ Π² ΠΎΠ΄Π½ΠΈΡ Π°Π΄ΡΠ΅ΡΠ°Ρ int i; float f; void *p; char *s; ... } } D[Dsz]; int Dp=0; #define PUSH(X) { D[Dp++]=X; } #define POP(X) (D[--Dp])C ++: generalizing the task - a heterogeneous container is required that can store arbitrary data types (for example, a list in Python or Lisp). Implemented through
- type tree inherited from a single
ΠΏΠΎΠ»ΠΈΠΌΠΎΡΡΠ½ΠΎΠ³ΠΎbase class - any STL containers store pointers to the base class
Base* - all work with objects needs to be implemented through
Base*, the definition of a specific type,typeid(Base*number)anddymanic_cast<Int*>(number)->...
- type tree inherited from a single
struct Base { virtual ~Base(); // Π΄Π»Ρ Π±Π°Π·ΠΎΠ²ΠΎΠ³ΠΎ ΠΊΠ»Π°ΡΡΠ° Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΠ° // 1+ Π²ΠΈΡΡΡΠ°Π»ΡΠ½Π°Ρ ΡΡΠ½ΠΊΡΠΈΡ // ΠΏΠΎ ΠΊΠ»Π°ΡΡΠΈΠΊΠ΅: [ΠΏΡΡΡΠΎΠΉ] Π²ΠΈΡΡΡΠ°Π»ΡΠ½ΡΠΉ Π΄Π΅ΡΡΡΡΠΊΡΠΎΡ virtual string dot(); // Π΄Π»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΡΠΈΠΏΠ° ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² Π½ΡΠΆΠ½Π° // ΡΠ²ΠΎΡ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ ΡΠ»ΠΎΠ²Π° <ΡΠΎΡΠΊΠ°> string val; // ΡΡΡΠΎΠΊΠ° -- ΡΠ½ΠΈΠ²Π΅ΡΡΠ°Π»ΡΠ½ΡΠΉ ΡΠΎΡΠΌΠ°Ρ Π΄Π°Π½Π½ΡΡ
: // Π»ΡΠ±ΡΠ΅ Π΄Π°Π½Π½ΡΠ΅ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡΠ΅Π΄ΡΡΠ°Π²ΠΈΡΡ Π² ΡΠ΅ΠΊΡΡΠΎΠ²ΠΎΠΌ Π²ΠΈΠ΄Π΅, // Π² ΡΠ°ΡΡΠ½ΠΎΡΡΠΈ ΠΈΠΌΠ΅Π½Π° ΡΠ»ΠΎΠ² vector<Base*> bytecode; // ΠΏΠΎΠ½Π°Π΄ΠΎΠ±ΠΈΡΡΡ ΠΊΠΎΠ³Π΄Π° Π½Π°ΡΠ½Π΅ΠΌ ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²ΡΠ²Π°ΡΡ // ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΡ ΡΠ»ΠΎΠ² virtual add(Base*); // ΡΡΠ½ΠΊΡΠΈΠΈ Π±Π°Π·ΠΎΠ²ΠΎΠΉ Π°ΡΠΈΡΠΌΠ΅ΡΠΈΠΊΠΈ virtual sub(Base*); virtual mul(Base*); virtual div(Base*); ... }; Data stack:
stack<Base*> DataStack; // (!!!) Ρ
ΡΠ°Π½ΠΈΠΌ Π½Π΅ ΠΎΠ±ΡΠ΅ΠΊΡΡ, Π° ΡΠΊΠ°Π·Π°ΡΠ΅Π»ΠΈ Π½Π° Π½ΠΈΡ
Stack of returns:
stack<Base*> ReturnStack; Dictionaries
struct Vocabulary:Base; Vocabulary FORTH("FORTH",NULL); struct Vocabulary:Base { Vocabulary(string name,Vocabulary*next=&FORTH); Vocabulary* next; // Π΄Π»Ρ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ Π΄Π΅ΡΠ΅Π²Π° ΡΠ»ΠΎΠ²Π°ΡΠ΅ΠΉ Π΄Π»Ρ ΠΏΠΎΠΈΡΠΊΠ° map<string,Base*> words; // Ρ
ΡΠ°Π½ΠΈΠ»ΠΈΡΠ΅ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΠΉ Base* Find(string); // ΡΡΠ½ΠΊΡΠΈΡ ΡΠ΅ΠΊΡΡΡΠΈΠ²Π½ΠΎΠ³ΠΎ ΠΏΠΎΠΈΡΠΊΠ° words/*next }; Vocabulary FORTH; We inherit the types we want to work with:
Integers (only numbers, not addresses):
struct Int: Base { int val; // (!) ΠΎΠ±ΠΎΡΠ°ΡΠΈΠ²Π°Π΅ΠΌ Π½ΡΠΆΠ½ΡΠΉ ΡΠΈΠΏ Int(std::string); Int(int); string dot(); // ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΎΡΡ ΠΈ Π΄Π°ΠΌΠΏ int add(Base*); int sub(Base*); ... }; // Π²ΡΡΠΈΡΠ»Π΅Π½ΠΈΡ At one time, there was a terrible lack of a floating point, and the float / str (1) encoding / decoding words, even had to intXXh hang a resident calculator written in TurboC (1) for calculations it was elementary to use the FPU stack)
struct Float: Base { float val ; // (!) ΠΎΠ±ΠΎΡΠ°ΡΠΈΠ²Π°Π΅ΠΌ Π½ΡΠΆΠ½ΡΠΉ ΡΠΈΠΏ Float(string); Float(float); string dot(); ... }; Pointers
struct Ptr: Base { Ptr(void*); void *val; }; |
boost::any. - VladD