interpeter ל brainf***, ול Befunge - עמוד 2 - תכנות - HWzone פורומים
עבור לתוכן
  • צור חשבון

interpeter ל brainf***, ול Befunge


Jaman

Recommended Posts

אם אתה רוצה לכתוב קומפיילר ממש, אתה צריך להבין את הפלטפורמה אליה אתה מקמפל. זה כולל גם אסמבלי, וגם את מערכת ההפעלה אליה אתה מקמפל, ועוד כל מני קונבנציות אחרות.

אולי יותר קל לייצר קובץ EXE שמכיל interpreter שקימפלת ב-C וכן קוד BF שירוץ בעזרת ה-interpreter.

קישור לתוכן
שתף באתרים אחרים

אולי יותר קל לייצר קובץ EXE שמכיל interpreter שקימפלת ב-C וכן קוד BF שירוץ בעזרת ה-interpreter.

אבל אני לא אשיג פה שום דבר בעצם :P (מבחינת לימוד עצמי).

בכל מקרה, החלטתי לעשות interpreter גם ל Befunge-98 י(http://quadium.net/funge/spec98.html),

על הקומפיילר אני אוותר מראש משום שהשפה הומצאה בנסיון להמציא שפה הכי קשה לקימפול שאפשר :).

אעדכן פה כשאסיים.

קישור לתוכן
שתף באתרים אחרים

כתבתי כבר חלק גדול מהתוכנית, אבל כשניסיתי לבדוק חלק ממה שכתבתי נתקלתי בבעיה מהותית.

ישמתי ערימה (stack) בצורה הזו:


template <class T>
struct node
{
T data;
node *next;
};

template <class T>
class stack
{
private:
int stack_size;
node<T>* stack_top;
public:
stack() {stack_size = 0 ; stack_top = NULL;};
~stack();
int size() {return stack_size;};
bool empty() {return !!size();}
void push(T);
T pop();
T top();
void clear();
};

template <class T>
void stack<T>::push(T a)
{
node<T> *n = new node<T>;
n->data = a;
n->next = stack_top;
stack_top = n;
stack_size++;
}

template <class T>
T stack<T>::pop()
{
if (stack_size == 0)
error("Tried to pop from an empty stack");

T res = stack_top->data;
node<T>* tmp = stack_top->next;
delete stack_top;
stack_top = tmp;
stack_size--;
return res;
}

template <>
cell stack<cell>::pop()
{
if (stack_size == 0)
return 0;

cell res = stack_top->data;
node<cell>* tmp = stack_top->next;
delete stack_top;
stack_top = tmp;
stack_size--;
return res;
}

template <class T>
T stack<T>::top()
{
if (stack_size == 0)
error("Tried to get the top value from an empty stack");

return stack_top->data;
}

template <class T>
void stack<T>::clear()
{
while (stack_top)
pop();
}

template <class T>
stack<T>::~stack() {clear();}

לאחר מכן ב main יצרתי ערימה של ערימות של תאים

stack< stack<cell> > ss;
{
stack<cell> empty_stack;
ss.push(empty_stack);
}

אבל משום מה אני לא מצליח לדחוף תאים לערימה הראשונה ב ss, ואני כן יכול לדחוף תאים לערימות תאים רגילות:

ss.top().push(7);
stack<cell> toss = ss.top();
stack<cell> h;
h.push(6);
cout << ss.top().pop() << endl << h.pop() << endl << toss.pop();
toss.push(2);
cout << endl << toss.pop();

OUTPUT:
0
6
0
2

וגם בעזרת ה debugger רואים שבערימה הראשונה של ss אין תאים, בעוד שבערימות תאים אחרות יש.

cell אגב מוגדר ככה:

typedef long int cell;

מישהו יכול לעזור לי לפענח את הבעיה המוזרה הזאת :?

קישור לתוכן
שתף באתרים אחרים

אפשר שאלה: למה אתה לא משתמש ב STL?

רק באמצע שיישמתי את stack חשבתי להשתמש בסיפריה (סכה"כ זו פעם ראשונה שאני צריך ערימה).

אני דווקא משתמש בווקטורים בתוכנית.

אבל מעניין אותי לדעת האם ואיך הייתי יכול ליישם specialization כזה

template <>
cell stack<cell>::pop()
{
if (stack_size == 0)
return 0;

cell res = stack_top->data;
node<cell>* tmp = stack_top->next;
delete stack_top;
stack_top = tmp;
stack_size--;
return res;
}

במידה והייתי משתמש בסיפריה בשביל stack?

Jaman, הייתי ממליץ לך לערוך את הכותרת כך שתהיה יותר רלוונטית לנושא.

ערכתי.

קישור לתוכן
שתף באתרים אחרים

השיטה ()top (וגם pop) של המחלקה stack של STL מתנהגת בצורה מסוימת עבור כל הטיפוסים. אני רוצה שהיא תתנהג בצורה שונה עבור הטיפוס cell.

האם ואיך אפשר לעשות את זה?

קישור לתוכן
שתף באתרים אחרים

לא מומלץ, כי זה דורש להיכנס לנבכי ה-STL, והקוד שלך יהיה לא פורטבילי, וקשה לתחזוק. וחוץ מזה, אי אפשר לשנות את החתימה של הפונקציה.

הדבר החכם לעשות הוא לעטוף את ה-stack בטיפוס משלך - תגדיר מחלקה שתייצג מחסנית, ושתחזיק בתוכה stack (או deque) של STL. תממש את הפונקציות של המחלקה ע"י קריאה לפונקציות המתאימות ב-stack (מה שנקרא delegation). אם אתה רוצה לשנות את אופן הפעולה של פונקציה מסויימת, אז פשוט שנה אותה במקום לקרוא ישירות לפונקציה המתאימה של ה-stack.

אופציה שנייה היא שהמחלקה שלך תירש מ-<stack<Cell, ואז אוטומטית תקבל את כל הפונקציות שלו בלי צורך לעשות דלגציה. בעקרון תוכל להגדיר מחדש את הפונקציה pop (וכך לדרוך על הפונקציה הקיימת), אבל זה לא מומלץ (ראה כאן או כאן), או שתגדיר פשוט פונקציה חדשה (עם שם אחר) שעושה מה שאתה רוצה.

קישור לתוכן
שתף באתרים אחרים

האינטרפרטר שלי בנתיים מכיר את כל הפקודות של befunge-93, ולחלק מן הפקודות של befunge-98 (את החלק שאין אשלים אחרי שאבין בדיוק צריך לעבוד הקטע עם ה storage offset).

אני מצרף את הקוד שלו, את הקובץ הבינארי, וכמה תוכניות befunge שאפשר לבדוק עליו.

כמה נקודות:

-מכיוון שהספסיפיקציה של השפה לא ברורה מספיק בחלק מן הפקודות אפשר ליישם אותן בדרכים קצת שונות. לכן ישנן תוכניות שעובדות על אינטרפרטר אחד, אבל לא על אחר, ובגלל זה כנראה חלק מהתוכנות הצירפתי לא עובדות על האינטרפרטר שלי (את התוכניות לא אני כתבתי).

-בגלל שלא חשבתי על כל ההיבטים של האינטפרטר עד הסוף בהתחלה יצא שחלק מהקוד קצת לא מובן בחלקים מסויימים, ומיושם בדרך-לא דרך (ע"ע הפקודה k, והמחלקה funge-space).

-אם במקרה מישהו פה מכיר את השפה ומבין את הקטע של ה storage offset (ב funge 98) אשמח אם הוא יסביר לי אותו.

[attachment deleted by admin]

קישור לתוכן
שתף באתרים אחרים

ארכיון

דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.

×
  • צור חדש...