run time type information made by self

26/02/2012 - 17:08 von Jens Kallup | Report spam
Hallo Gemeinde.

Heute mal was C++ behaftetes:
wie ist es möglich, RTTI in Assembler umzusetzen?
zum Problem:
- ich schreibe derzeit (immer noch) einen Compiler.
- nun bin ich bei folgenden Code, der Übersetzt werden soll:

CLASS FormularA OF FORM

with (this) // RTTI für FORM
top 100
...
endwith

this.pushbutton1 = new PushButton(this)
with (this.pushbutton1) // RTTI für form.pushbutton1
top 10
...
endwith

...

ENDCLASS

- wie ist es nun möglich, für verschiedene Klassentypen RTTI
zu setzen?

Ein einfaches Beispiel für Windows 32 Bit wàre nicht schlect.
Gru0
Jens

zur Zeit habe ich bereits folgenden Code:

// hier müsste noch RTTI hinzu
1: this
fld qword [_LC35]
fstp qword [_LCtmp]
push dword [_LCtmp+4]
push dword [_LCtmp]
push dword _LCtop
call _set_exp_var

_LC35: dq 100.0
_LCtmp: dq 0.0
_LCtop: db "top",0


den Code übersetze wie folgt:


#define OT__FORM 0
struct obj__struct
{
QString name;
int type;
struct obj__struct *next;
};

struct obj__struct* obj_struct = NULL;
QList <obj__struct* > obj_type;
int object_type = 0;


%%

class_stmt
: _CLASS_ _ID_ _OF_ _ID_ {
if (!strcmp($4,"form"))
{
code_str += QString(
"\tcall _LForm_%1"
).arg($2);

object_type = OT__FORM;
}
code_str += QString("\tleave\tret");
code_str += QString(
"_LForm_%1:"
"\tpush ebp"
"\tmov ebp, esp"
).arg($2);
} with_stmt _ENDCLASS_ {
code_str += QString(
"\tpush dword 0"
"\tcall _exit"
"\tleave\tret");
}
;

with_stmt
: { }
| _WITH_ _OBR_ {

if (!obj_type.isEmpty())
obj_type.clear();

} with_this {
obj_type << obj_struct;
} _CBR_ object_vars _ENDWITH_
;

with_this
: _ID_
{
obj_struct = new obj__struct;
obj_struct->name = $1;
obj_struct->type = object_type;
obj_struct->next = NULL;

code_str += QString("1: %1").arg($1);
}
| _ID_ _POINT_ with_this
{
struct obj__struct *ptr = new obj__struct;
ptr->name = $1;
ptr->type = object_type;
ptr->next = NULL;
obj_struct->next = ptr;

code_str += QString("2: %1.").arg($1);
}
;

object_vars
: { }
| _ID_ _ASSIGN_ exp {
code_str += QString(
"\tfstp qword [_LCtmp]"
"\tpush dword [_LCtmp+4]"
"\tpush dword [_LCtmp]"
"\tpush dword _LC%1"
"\tcall _set_exp_var"
"\tadd esp, 16"
)
.arg($1);
}
| _ID_ _ASSIGN_ handle_string {
code_str += QString(
"\tpush _LC%1"
"\tcall _set_str_var"
).arg($1);
}
;
 

Lesen sie die antworten

#1 Stefan Reuther
26/02/2012 - 18:40 | Warnen spam
Jens Kallup wrote:
Heute mal was C++ behaftetes:
wie ist es möglich, RTTI in Assembler umzusetzen?
zum Problem:
- ich schreibe derzeit (immer noch) einen Compiler.



Ich habe irgendwie, schon seit mehreren Postings, den Eindruck, dass du
dir deutlich zu viel auf einmal vorgenommen hast.

- nun bin ich bei folgenden Code, der Übersetzt werden soll:

CLASS FormularA OF FORM

with (this) // RTTI für FORM
top 100
...
endwith



Was meinst du hier mit RTTI? Virtuelle Funktionsaufrufe?

Der meiner Meinung nach sinnvollste Ansatz, einen Compiler für eine
halbwegs moderne Programmiersprache zu bauen, ist, sich erstmal eine
Übersetzung in eine einfache Programmiersprache zu überlegen, zum
Beispiel C.

Ich weiß jetzt nicht, wie deine Programmiersprache funktionieren soll,
aber angenommen, du hàttest einen Klassentyp 'Form', der eine virtuelle
Methode 'top' mit einem Parameter hat, dann gàbe es für diese Klasse
eine virtuelle Funktionstabelle, die einen Zeiger auf diese Methode enthàlt.
struct form_vtbl {
void (*top)(void* self, int y);
/* Und noch weitere Methoden: */
void (*left)(void* self, int x);
void (*width)(void* self, int w);
};
Die Klasse 'form' wàre dann
struct form {
struct form_vtbl* vtbl;
/* Und jetzt die Attribute: */
int x;
int y;
int w;
};
Beim Anlegen eines 'form' würde der vtbl-Zeiger auf eine Tabelle mit den
Methoden gesetzt:
static struct form_vtbl the_form_vtbl = {
form_top, form_left, form_widht
};
Die Methode 'top' könnte dann so aussehen:
void form_top(void* self, int y) {
struct form* me = self;
me->y = y;
}
Und ein Aufruf
with (this)
top 100
left i+1
end
wàre in C z.B.
struct form* p = this; /* hier den Ausdruck 'this' auswerten */
p->vtbl->top(p, 100);
p->vtbl->left(p, i+1);

Das, was man in C++ RTTI nennt, nàmlich, dass eine Klasse Auskunft über
ihren Namen geben oder in andere Klassentypen konvertiert werden kann,
kann man als eine weitere virtuelle Methode implementieren, z.B.
const char* form_typename(void* self) {
return "form";
}
void* form_dynamic_cast(void* self, const char* target) {
/* form kann nach form, widget und object gecastet werden */
if (strcmp(target, "form") == 0
|| strcmp(target, "widget") == 0
|| strcmp(target, "object") == 0)
{
return self;
} else {
return 0;
}
}

So, und das jetzt alles nach Assembler zu übersetzen, sollte nicht mehr
weiter schwer sein.

Ob du dann direkt aus dem Quellcode Assembler erzeugst, ist dann dir
überlassen, aber eine direkte Überlegung "wie übersetze ich (z.B.)
std::map<std::string, std::string>::find nach Assembler" dürfte
unpraktikabel sein.


Stefan

Ähnliche fragen