stage2: reference support (refs)
- Builtin refs: int& -> int* in signature, (*a) deref in body - Class refs: Cls& -> Cls* in signature, p.field -> p->field in body - Call-site & injection via FnRef table (swap(x,y) -> swap(&x,&y)) - Member call ref args also get & injected - Virtual dispatch for pointer-ref params preserved - parse_member_decl: ptr param recording + dot-to-arrow conversion - parse_function: iref body rewrite + fnref call-site rewrite
这个提交包含在:
二进制
二进制文件未显示。
+365
-5
@@ -37,6 +37,41 @@ static int g_line = 1;
|
|||||||
static int g_ns_open = 0; /* namespace block depth (flattened) */
|
static int g_ns_open = 0; /* namespace block depth (flattened) */
|
||||||
static int g_virt_pending = 0; /* next member decl is virtual */
|
static int g_virt_pending = 0; /* next member decl is virtual */
|
||||||
|
|
||||||
|
/* ---------------- references ---------------- */
|
||||||
|
typedef struct FnRef {
|
||||||
|
char fn[64];
|
||||||
|
int arg[16];
|
||||||
|
int narg;
|
||||||
|
struct FnRef *next;
|
||||||
|
} FnRef;
|
||||||
|
static FnRef *g_fnrefs = NULL;
|
||||||
|
static FnRef *find_fnref(const char *fn)
|
||||||
|
{
|
||||||
|
FnRef *p;
|
||||||
|
for (p = g_fnrefs; p; p = p->next)
|
||||||
|
if (!strcmp(p->fn, fn)) return p;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
static int fr_has_arg(const FnRef *fr, int ai)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < fr->narg; i++)
|
||||||
|
if (fr->arg[i] == ai) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static void add_fnref(const char *fn, int ai)
|
||||||
|
{
|
||||||
|
FnRef *p = find_fnref(fn);
|
||||||
|
if (!p) {
|
||||||
|
p = (FnRef*)calloc(1, sizeof *p);
|
||||||
|
strncpy(p->fn, fn, sizeof p->fn - 1);
|
||||||
|
p->fn[sizeof p->fn - 1] = 0;
|
||||||
|
p->next = g_fnrefs;
|
||||||
|
g_fnrefs = p;
|
||||||
|
}
|
||||||
|
if (p->narg < 16) p->arg[p->narg++] = ai;
|
||||||
|
}
|
||||||
|
|
||||||
/* ---------------- templates ---------------- */
|
/* ---------------- templates ---------------- */
|
||||||
|
|
||||||
typedef struct TplFn {
|
typedef struct TplFn {
|
||||||
@@ -523,12 +558,16 @@ static void proto_emit(const char *fmt, ...)
|
|||||||
static void gather_decl(char *type, int typesz, char *name, int namesz);
|
static void gather_decl(char *type, int typesz, char *name, int namesz);
|
||||||
static int tpl_call_check(char varcls[][128], char varname[][64], int nvars);
|
static int tpl_call_check(char varcls[][128], char varname[][64], int nvars);
|
||||||
|
|
||||||
static void parse_member_decl(const char *cls, const char *ret_type,
|
static void parse_member_decl(const char *cls, const char *ret_type, const char *mname_in, int is_virt)
|
||||||
const char *mname_in, int is_virtual)
|
|
||||||
{
|
{
|
||||||
char name[256];
|
char name[256];
|
||||||
char mname[256];
|
char mname[256];
|
||||||
int is_ctor, is_dtor;
|
int is_ctor, is_dtor;
|
||||||
|
char bptrcls[64][128], bptrname[64][64];
|
||||||
|
int bnptrs = 0;
|
||||||
|
char biref[64][64];
|
||||||
|
int bn_iref = 0;
|
||||||
|
int sig_pidx = 0;
|
||||||
ClassInfo *ci = find_class(cls);
|
ClassInfo *ci = find_class(cls);
|
||||||
|
|
||||||
if (mname_in && mname_in[0])
|
if (mname_in && mname_in[0])
|
||||||
@@ -543,7 +582,7 @@ static void parse_member_decl(const char *cls, const char *ret_type,
|
|||||||
if (is_dtor) ci->has_dtor = 1;
|
if (is_dtor) ci->has_dtor = 1;
|
||||||
else add_member(ci, name);
|
else add_member(ci, name);
|
||||||
/* record virtual methods (name + trimmed return type) */
|
/* record virtual methods (name + trimmed return type) */
|
||||||
if (is_virtual && !is_ctor && !is_dtor && ci->n_virt < 16) {
|
if (is_virt && !is_ctor && !is_dtor && ci->n_virt < 16) {
|
||||||
char rtb[64];
|
char rtb[64];
|
||||||
int rl;
|
int rl;
|
||||||
snprintf(rtb, sizeof rtb, "%s", ret_type);
|
snprintf(rtb, sizeof rtb, "%s", ret_type);
|
||||||
@@ -609,10 +648,29 @@ static void parse_member_decl(const char *cls, const char *ret_type,
|
|||||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, ")")) depth--;
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, ")")) depth--;
|
||||||
/* class type param -> struct Class */
|
/* class type param -> struct Class */
|
||||||
if (g_tok.type == T_IDENT && find_class(g_tok.text)) {
|
if (g_tok.type == T_IDENT && find_class(g_tok.text)) {
|
||||||
|
char ptcls[128];
|
||||||
|
strncpy(ptcls, g_tok.text, sizeof ptcls - 1);
|
||||||
|
ptcls[sizeof ptcls - 1] = 0;
|
||||||
proto_emit(" struct %s", g_tok.text);
|
proto_emit(" struct %s", g_tok.text);
|
||||||
strncat(g_params, " struct ", sizeof g_params - strlen(g_params) - 1);
|
strncat(g_params, " struct ", sizeof g_params - strlen(g_params) - 1);
|
||||||
strncat(g_params, g_tok.text, sizeof g_params - strlen(g_params) - 1);
|
strncat(g_params, g_tok.text, sizeof g_params - strlen(g_params) - 1);
|
||||||
next_tok();
|
next_tok();
|
||||||
|
/* handle * or & suffix: convert to pointer param */
|
||||||
|
if (g_tok.type == T_PUNCT &&
|
||||||
|
(!strcmp(g_tok.text, "*") || !strcmp(g_tok.text, "&"))) {
|
||||||
|
int is_ref = !strcmp(g_tok.text, "&");
|
||||||
|
proto_emit(" *");
|
||||||
|
strncat(g_params, " *", sizeof g_params - strlen(g_params) - 1);
|
||||||
|
next_tok();
|
||||||
|
/* record ptr param for body dispatch */
|
||||||
|
if (g_tok.type == T_IDENT && bnptrs < 64) {
|
||||||
|
strncpy(bptrcls[bnptrs], ptcls, 127);
|
||||||
|
strncpy(bptrname[bnptrs], g_tok.text, 63);
|
||||||
|
bnptrs++;
|
||||||
|
}
|
||||||
|
if (is_ref)
|
||||||
|
add_fnref(mname, sig_pidx);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* smart spacing for prototype params */
|
/* smart spacing for prototype params */
|
||||||
@@ -620,12 +678,19 @@ static void parse_member_decl(const char *cls, const char *ret_type,
|
|||||||
const char *tt = g_tok.text;
|
const char *tt = g_tok.text;
|
||||||
int c = tt[0];
|
int c = tt[0];
|
||||||
if (g_tok.type == T_PUNCT) {
|
if (g_tok.type == T_PUNCT) {
|
||||||
|
if (c == '&') {
|
||||||
|
/* reference param -> pointer param */
|
||||||
|
proto_emit("*");
|
||||||
|
strncat(g_params, " *", sizeof g_params - strlen(g_params) - 1);
|
||||||
|
add_fnref(mname, sig_pidx);
|
||||||
|
} else {
|
||||||
if (!(c == ')' || c == ']' || c == ';' || c == ',' ||
|
if (!(c == ')' || c == ']' || c == ';' || c == ',' ||
|
||||||
c == '*' || c == '&' || c == '(' ))
|
c == '*' || c == '&' || c == '(' ))
|
||||||
proto_emit(" ");
|
proto_emit(" ");
|
||||||
proto_emit("%s", tt);
|
proto_emit("%s", tt);
|
||||||
strncat(g_params, " ", sizeof g_params - strlen(g_params) - 1);
|
strncat(g_params, " ", sizeof g_params - strlen(g_params) - 1);
|
||||||
strncat(g_params, tt, sizeof g_params - strlen(g_params) - 1);
|
strncat(g_params, tt, sizeof g_params - strlen(g_params) - 1);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
proto_emit(" %s", tt);
|
proto_emit(" %s", tt);
|
||||||
strncat(g_params, " ", sizeof g_params - strlen(g_params) - 1);
|
strncat(g_params, " ", sizeof g_params - strlen(g_params) - 1);
|
||||||
@@ -675,6 +740,17 @@ static void parse_member_decl(const char *cls, const char *ret_type,
|
|||||||
int prev_dot = 0;
|
int prev_dot = 0;
|
||||||
while (bd > 0) {
|
while (bd > 0) {
|
||||||
if (g_tok.type == T_EOF) break;
|
if (g_tok.type == T_EOF) break;
|
||||||
|
/* builtin ref param: a -> (*a) */
|
||||||
|
if (g_tok.type == T_IDENT && bn_iref > 0) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < bn_iref; i++)
|
||||||
|
if (!strcmp(g_tok.text, biref[i])) break;
|
||||||
|
if (i < bn_iref) {
|
||||||
|
proto_emit(" (*%s)", g_tok.text);
|
||||||
|
next_tok();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
/* namespace-qualified name: ns::name -> name */
|
/* namespace-qualified name: ns::name -> name */
|
||||||
if (g_tok.type == T_IDENT && !find_class(g_tok.text)) {
|
if (g_tok.type == T_IDENT && !find_class(g_tok.text)) {
|
||||||
Token nxt;
|
Token nxt;
|
||||||
@@ -838,7 +914,85 @@ static void parse_member_decl(const char *cls, const char *ret_type,
|
|||||||
next_tok();
|
next_tok();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
/* ptr/var member dispatch: p->method / p.field */
|
||||||
|
if (g_tok.type == T_IDENT && bnptrs > 0) {
|
||||||
|
int pi;
|
||||||
|
for (pi = 0; pi < bnptrs; pi++) {
|
||||||
|
if (!strcmp(g_tok.text, bptrname[pi])) {
|
||||||
|
Token t1, t2;
|
||||||
|
read_tok(&t1);
|
||||||
|
if (t1.type == T_PUNCT && !strcmp(t1.text, "->")) {
|
||||||
|
read_tok(&t2);
|
||||||
|
if (t2.type == T_IDENT) {
|
||||||
|
Token t3;
|
||||||
|
read_tok(&t3);
|
||||||
|
if (t3.type == T_PUNCT && !strcmp(t3.text, "(")) {
|
||||||
|
char meth[128], mname[256];
|
||||||
|
ClassInfo *pci = find_class(bptrcls[pi]);
|
||||||
|
strncpy(meth, t2.text, sizeof meth - 1);
|
||||||
|
meth[sizeof meth - 1] = 0;
|
||||||
|
if (is_virtual(pci, meth)) {
|
||||||
|
proto_emit(" %s->__vtbl->%s(%s",
|
||||||
|
g_tok.text, meth, g_tok.text);
|
||||||
|
} else {
|
||||||
|
snprintf(mname, sizeof mname, "%s_%s",
|
||||||
|
bptrcls[pi], meth);
|
||||||
|
proto_emit(" %s(%s", mname, g_tok.text);
|
||||||
|
}
|
||||||
|
next_tok(); next_tok(); next_tok();
|
||||||
|
if (!(g_tok.type == T_PUNCT && !strcmp(g_tok.text, ")"))) {
|
||||||
|
proto_emit(", ");
|
||||||
|
int ad = 0;
|
||||||
|
while (!(g_tok.type == T_PUNCT && !strcmp(g_tok.text, ")") && ad == 0)) {
|
||||||
|
if (g_tok.type == T_EOF) break;
|
||||||
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "(")) ad++;
|
||||||
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, ")")) ad--;
|
||||||
|
proto_emit(" %s", g_tok.text);
|
||||||
|
next_tok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
proto_emit(")");
|
||||||
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, ")")) next_tok();
|
||||||
|
prev_dot = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
unread_tok(&t3);
|
||||||
|
}
|
||||||
|
unread_tok(&t2);
|
||||||
|
} else if (t1.type == T_PUNCT && !strcmp(t1.text, ".")) {
|
||||||
|
unread_tok(&t1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
unread_tok(&t1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/* fall-through: emit token as-is */
|
/* fall-through: emit token as-is */
|
||||||
|
/* ptr ref: p.field -> p->field (fix dot to arrow for known ptr vars) */
|
||||||
|
if (g_tok.type == T_IDENT && bnptrs > 0) {
|
||||||
|
int pi2;
|
||||||
|
for (pi2 = 0; pi2 < bnptrs; pi2++) {
|
||||||
|
if (!strcmp(g_tok.text, bptrname[pi2])) {
|
||||||
|
Token nxt2;
|
||||||
|
read_tok(&nxt2);
|
||||||
|
if (nxt2.type == T_PUNCT && !strcmp(nxt2.text, ".")) {
|
||||||
|
Token nxt3;
|
||||||
|
read_tok(&nxt3);
|
||||||
|
if (nxt3.type == T_IDENT) {
|
||||||
|
proto_emit("%s->%s", g_tok.text, nxt3.text);
|
||||||
|
/* consumed '.', field by read_tok; skip 'p' via next_tok */
|
||||||
|
next_tok(); /* consume 'p' from g_tok */
|
||||||
|
prev_dot = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
unread_tok(&nxt3);
|
||||||
|
}
|
||||||
|
unread_tok(&nxt2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
prev_dot = (g_tok.type == T_PUNCT &&
|
prev_dot = (g_tok.type == T_PUNCT &&
|
||||||
(!strcmp(g_tok.text, ".") || !strcmp(g_tok.text, "->")));
|
(!strcmp(g_tok.text, ".") || !strcmp(g_tok.text, "->")));
|
||||||
proto_emit(" %s", g_tok.text);
|
proto_emit(" %s", g_tok.text);
|
||||||
@@ -1126,6 +1280,18 @@ static void parse_member_definition(const char *ret_type)
|
|||||||
if (g_tok.type == T_IDENT && find_class(g_tok.text)) {
|
if (g_tok.type == T_IDENT && find_class(g_tok.text)) {
|
||||||
emit(" struct %s", g_tok.text);
|
emit(" struct %s", g_tok.text);
|
||||||
next_tok();
|
next_tok();
|
||||||
|
/* handle * or & suffix */
|
||||||
|
if (g_tok.type == T_PUNCT &&
|
||||||
|
(!strcmp(g_tok.text, "*") || !strcmp(g_tok.text, "&"))) {
|
||||||
|
emit(" *");
|
||||||
|
next_tok();
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* builtin ref param: type &name -> type *name */
|
||||||
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "&")) {
|
||||||
|
emit("*");
|
||||||
|
next_tok();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
emit_tok();
|
emit_tok();
|
||||||
@@ -1706,6 +1872,9 @@ static void parse_function(const char *ret_type, const char *name)
|
|||||||
char ptrcls[64][128]; /* pointer variable name -> class name */
|
char ptrcls[64][128]; /* pointer variable name -> class name */
|
||||||
char ptrname[64][64];
|
char ptrname[64][64];
|
||||||
int nptrs = 0;
|
int nptrs = 0;
|
||||||
|
char iref[64][64]; /* builtin-type reference params (deref in body) */
|
||||||
|
int n_iref = 0;
|
||||||
|
int sig_pidx = 0; /* param index while scanning signature */
|
||||||
|
|
||||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "::")) {
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "::")) {
|
||||||
/* member function: class is 'name', method follows */
|
/* member function: class is 'name', method follows */
|
||||||
@@ -1742,14 +1911,21 @@ static void parse_function(const char *ret_type, const char *name)
|
|||||||
/* signature: class types need 'struct'; class params are recorded */
|
/* signature: class types need 'struct'; class params are recorded */
|
||||||
while (!(g_tok.type == T_PUNCT && !strcmp(g_tok.text, "{"))) {
|
while (!(g_tok.type == T_PUNCT && !strcmp(g_tok.text, "{"))) {
|
||||||
if (g_tok.type == T_EOF) break;
|
if (g_tok.type == T_EOF) break;
|
||||||
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, ",")) {
|
||||||
|
sig_pidx++;
|
||||||
|
emit_tok();
|
||||||
|
next_tok();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (g_tok.type == T_IDENT && find_class(g_tok.text)) {
|
if (g_tok.type == T_IDENT && find_class(g_tok.text)) {
|
||||||
char clsname[128];
|
char clsname[128];
|
||||||
Token nxt;
|
Token nxt;
|
||||||
strncpy(clsname, g_tok.text, sizeof clsname - 1);
|
strncpy(clsname, g_tok.text, sizeof clsname - 1);
|
||||||
clsname[sizeof clsname - 1] = 0;
|
clsname[sizeof clsname - 1] = 0;
|
||||||
read_tok(&nxt);
|
read_tok(&nxt);
|
||||||
if (nxt.type == T_PUNCT && !strcmp(nxt.text, "*")) {
|
if (nxt.type == T_PUNCT &&
|
||||||
/* Cls* name -> struct Cls* name (pointer param) */
|
(!strcmp(nxt.text, "*") || !strcmp(nxt.text, "&"))) {
|
||||||
|
/* Cls* / Cls& name -> struct Cls* name (pointer param) */
|
||||||
emit(" struct %s*", clsname);
|
emit(" struct %s*", clsname);
|
||||||
next_tok(); /* g_tok = param name */
|
next_tok(); /* g_tok = param name */
|
||||||
if (g_tok.type == T_IDENT && nptrs < 64) {
|
if (g_tok.type == T_IDENT && nptrs < 64) {
|
||||||
@@ -1758,6 +1934,8 @@ static void parse_function(const char *ret_type, const char *name)
|
|||||||
nptrs++;
|
nptrs++;
|
||||||
emit(" %s", g_tok.text);
|
emit(" %s", g_tok.text);
|
||||||
next_tok();
|
next_tok();
|
||||||
|
if (!strcmp(nxt.text, "&"))
|
||||||
|
add_fnref(name, sig_pidx);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1774,6 +1952,24 @@ static void parse_function(const char *ret_type, const char *name)
|
|||||||
}
|
}
|
||||||
emit(" struct %s", clsname);
|
emit(" struct %s", clsname);
|
||||||
unread_tok(&nxt);
|
unread_tok(&nxt);
|
||||||
|
} else if (g_tok.type == T_IDENT && !find_class(g_tok.text)) {
|
||||||
|
/* builtin ref param: int &a -> int *a */
|
||||||
|
Token nxt;
|
||||||
|
read_tok(&nxt);
|
||||||
|
if (nxt.type == T_PUNCT && !strcmp(nxt.text, "&")) {
|
||||||
|
emit(" %s*", g_tok.text);
|
||||||
|
next_tok(); /* g_tok = param name */
|
||||||
|
if (g_tok.type == T_IDENT && n_iref < 64) {
|
||||||
|
strncpy(iref[n_iref], g_tok.text, 63);
|
||||||
|
iref[n_iref][63] = 0;
|
||||||
|
n_iref++;
|
||||||
|
}
|
||||||
|
add_fnref(name, sig_pidx);
|
||||||
|
emit(" %s", g_tok.text); /* emit param name */
|
||||||
|
next_tok();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
unread_tok(&nxt);
|
||||||
}
|
}
|
||||||
emit_tok();
|
emit_tok();
|
||||||
next_tok();
|
next_tok();
|
||||||
@@ -1797,6 +1993,64 @@ static void parse_function(const char *ret_type, const char *name)
|
|||||||
/* template function call: max(a, b) -> max_i(a, b) */
|
/* template function call: max(a, b) -> max_i(a, b) */
|
||||||
if (tpl_call_check(varcls, varname, nvars))
|
if (tpl_call_check(varcls, varname, nvars))
|
||||||
continue;
|
continue;
|
||||||
|
/* builtin ref param: a -> (*a) */
|
||||||
|
if (g_tok.type == T_IDENT && n_iref > 0) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < n_iref; i++)
|
||||||
|
if (!strcmp(g_tok.text, iref[i])) break;
|
||||||
|
if (i < n_iref) {
|
||||||
|
emit(" (*%s)", g_tok.text);
|
||||||
|
next_tok();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* function call with reference args: swap(x, y) -> swap(&x, &y) */
|
||||||
|
if (g_tok.type == T_IDENT) {
|
||||||
|
FnRef *fr = find_fnref(g_tok.text);
|
||||||
|
if (fr) {
|
||||||
|
Token nxt;
|
||||||
|
read_tok(&nxt);
|
||||||
|
if (nxt.type == T_PUNCT && !strcmp(nxt.text, "(")) {
|
||||||
|
unread_tok(&nxt); /* push '(' back — next_tok calls will consume properly */
|
||||||
|
int ai = 0, adepth = 0;
|
||||||
|
for (int ki = 0; ki < n_iref; ki++) fprintf(stderr, " iref[%d]=%s", ki, iref[ki]);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
for (int ki = 0; ki < fr->narg; ki++) fprintf(stderr, " DBG fnref arg[%d]=%d", ki, fr->arg[ki]);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
emit(" %s(", g_tok.text);
|
||||||
|
next_tok(); /* consume name */
|
||||||
|
next_tok(); /* consume '(' */
|
||||||
|
if (!(g_tok.type == T_PUNCT &&
|
||||||
|
!strcmp(g_tok.text, ")"))) {
|
||||||
|
for (;;) {
|
||||||
|
if (g_tok.type == T_EOF) break;
|
||||||
|
if (g_tok.type == T_PUNCT &&
|
||||||
|
!strcmp(g_tok.text, ")") && adepth == 0)
|
||||||
|
break;
|
||||||
|
if (g_tok.type == T_PUNCT &&
|
||||||
|
!strcmp(g_tok.text, "(")) adepth++;
|
||||||
|
if (g_tok.type == T_PUNCT &&
|
||||||
|
!strcmp(g_tok.text, ")")) adepth--;
|
||||||
|
if (g_tok.type == T_PUNCT &&
|
||||||
|
!strcmp(g_tok.text, ",") && adepth == 0) {
|
||||||
|
ai++;
|
||||||
|
emit(",");
|
||||||
|
next_tok();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (fr_has_arg(fr, ai)) emit("&");
|
||||||
|
emit_tok();
|
||||||
|
next_tok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emit(")");
|
||||||
|
if (g_tok.type == T_PUNCT &&
|
||||||
|
!strcmp(g_tok.text, ")")) next_tok();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
unread_tok(&nxt);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "{")) { depth++; emit(" {"); next_tok(); continue; }
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "{")) { depth++; emit(" {"); next_tok(); continue; }
|
||||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "}")) {
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "}")) {
|
||||||
if (depth > 0) { depth--; emit("}"); next_tok(); continue; }
|
if (depth > 0) { depth--; emit("}"); next_tok(); continue; }
|
||||||
@@ -1810,6 +2064,27 @@ static void parse_function(const char *ret_type, const char *name)
|
|||||||
clsname[sizeof clsname - 1] = 0;
|
clsname[sizeof clsname - 1] = 0;
|
||||||
emit(" struct %s", clsname);
|
emit(" struct %s", clsname);
|
||||||
next_tok();
|
next_tok();
|
||||||
|
/* reference declaration: Cls& r = p -> struct Cls* r = &p */
|
||||||
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "&")) {
|
||||||
|
emit(" *");
|
||||||
|
next_tok();
|
||||||
|
if (g_tok.type == T_IDENT && nptrs < 64) {
|
||||||
|
strncpy(ptrcls[nptrs], clsname, 127);
|
||||||
|
strncpy(ptrname[nptrs], g_tok.text, 63);
|
||||||
|
nptrs++;
|
||||||
|
emit(" %s", g_tok.text);
|
||||||
|
next_tok();
|
||||||
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "=")) {
|
||||||
|
emit(" = &");
|
||||||
|
next_tok();
|
||||||
|
if (g_tok.type == T_IDENT) {
|
||||||
|
emit(" %s", g_tok.text);
|
||||||
|
next_tok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
/* pointer declaration: Cls* p = ... */
|
/* pointer declaration: Cls* p = ... */
|
||||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "*")) {
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "*")) {
|
||||||
emit(" *");
|
emit(" *");
|
||||||
@@ -2050,6 +2325,7 @@ static void parse_function(const char *ret_type, const char *name)
|
|||||||
!strcmp(g_tok.text, ")"))) {
|
!strcmp(g_tok.text, ")"))) {
|
||||||
emit(", ");
|
emit(", ");
|
||||||
int adepth = 0;
|
int adepth = 0;
|
||||||
|
int carg = 0;
|
||||||
while (!(g_tok.type == T_PUNCT &&
|
while (!(g_tok.type == T_PUNCT &&
|
||||||
!strcmp(g_tok.text, ")") && adepth == 0)) {
|
!strcmp(g_tok.text, ")") && adepth == 0)) {
|
||||||
if (g_tok.type == T_EOF) break;
|
if (g_tok.type == T_EOF) break;
|
||||||
@@ -2057,6 +2333,17 @@ static void parse_function(const char *ret_type, const char *name)
|
|||||||
!strcmp(g_tok.text, "(")) adepth++;
|
!strcmp(g_tok.text, "(")) adepth++;
|
||||||
if (g_tok.type == T_PUNCT &&
|
if (g_tok.type == T_PUNCT &&
|
||||||
!strcmp(g_tok.text, ")")) adepth--;
|
!strcmp(g_tok.text, ")")) adepth--;
|
||||||
|
if (g_tok.type == T_PUNCT &&
|
||||||
|
!strcmp(g_tok.text, ",") && adepth == 0) {
|
||||||
|
carg++;
|
||||||
|
emit(",");
|
||||||
|
next_tok();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (carg < 16) {
|
||||||
|
FnRef *fr = find_fnref(mname);
|
||||||
|
if (fr && fr_has_arg(fr, carg)) emit("&");
|
||||||
|
}
|
||||||
emit_tok();
|
emit_tok();
|
||||||
next_tok();
|
next_tok();
|
||||||
}
|
}
|
||||||
@@ -2134,6 +2421,78 @@ static void parse_function(const char *ret_type, const char *name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* pointer member call / virtual dispatch: p->method(args) */
|
||||||
|
if (g_tok.type == T_IDENT && nptrs > 0) {
|
||||||
|
int pi;
|
||||||
|
for (pi = 0; pi < nptrs; pi++) {
|
||||||
|
if (!strcmp(g_tok.text, ptrname[pi])) {
|
||||||
|
Token t1;
|
||||||
|
read_tok(&t1);
|
||||||
|
if (t1.type == T_PUNCT && !strcmp(t1.text, "->")) {
|
||||||
|
/* method call via -> */
|
||||||
|
Token t2;
|
||||||
|
read_tok(&t2);
|
||||||
|
if (t2.type == T_IDENT) {
|
||||||
|
Token t3;
|
||||||
|
read_tok(&t3);
|
||||||
|
if (t3.type == T_PUNCT &&
|
||||||
|
!strcmp(t3.text, "(")) {
|
||||||
|
char meth[128], mname[256];
|
||||||
|
ClassInfo *pci = find_class(ptrcls[pi]);
|
||||||
|
strncpy(meth, t2.text, sizeof meth - 1);
|
||||||
|
meth[sizeof meth - 1] = 0;
|
||||||
|
if (is_virtual(pci, meth)) {
|
||||||
|
emit(" %s->__vtbl->%s(%s",
|
||||||
|
g_tok.text, meth, g_tok.text);
|
||||||
|
} else {
|
||||||
|
snprintf(mname, sizeof mname, "%s_%s",
|
||||||
|
ptrcls[pi], meth);
|
||||||
|
emit(" %s(%s", mname, g_tok.text);
|
||||||
|
}
|
||||||
|
next_tok();
|
||||||
|
next_tok();
|
||||||
|
next_tok();
|
||||||
|
if (!(g_tok.type == T_PUNCT &&
|
||||||
|
!strcmp(g_tok.text, ")"))) {
|
||||||
|
emit(", ");
|
||||||
|
int adepth = 0;
|
||||||
|
while (!(g_tok.type == T_PUNCT &&
|
||||||
|
!strcmp(g_tok.text, ")") &&
|
||||||
|
adepth == 0)) {
|
||||||
|
if (g_tok.type == T_EOF) break;
|
||||||
|
if (g_tok.type == T_PUNCT &&
|
||||||
|
!strcmp(g_tok.text, "(")) adepth++;
|
||||||
|
if (g_tok.type == T_PUNCT &&
|
||||||
|
!strcmp(g_tok.text, ")")) adepth--;
|
||||||
|
emit_tok();
|
||||||
|
next_tok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emit(")");
|
||||||
|
if (g_tok.type == T_PUNCT &&
|
||||||
|
!strcmp(g_tok.text, ")")) next_tok();
|
||||||
|
goto next_body_tok;
|
||||||
|
}
|
||||||
|
unread_tok(&t3);
|
||||||
|
}
|
||||||
|
unread_tok(&t2);
|
||||||
|
} else if (t1.type == T_PUNCT && !strcmp(t1.text, ".")) {
|
||||||
|
/* data member via ref: p.field -> p->field */
|
||||||
|
Token t2;
|
||||||
|
read_tok(&t2);
|
||||||
|
if (t2.type == T_IDENT) {
|
||||||
|
emit(" %s->%s", g_tok.text, t2.text);
|
||||||
|
next_tok(); /* consume '.' */
|
||||||
|
next_tok(); /* consume field name */
|
||||||
|
goto next_body_tok;
|
||||||
|
}
|
||||||
|
unread_tok(&t2);
|
||||||
|
}
|
||||||
|
unread_tok(&t1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/* class name used as type -> add 'struct' */
|
/* class name used as type -> add 'struct' */
|
||||||
if (g_tok.type == T_IDENT && find_class(g_tok.text)) {
|
if (g_tok.type == T_IDENT && find_class(g_tok.text)) {
|
||||||
emit(" struct %s", g_tok.text);
|
emit(" struct %s", g_tok.text);
|
||||||
@@ -2519,3 +2878,4 @@ int main(int argc, char **argv)
|
|||||||
if (g_out != stdout) fclose(g_out);
|
if (g_out != stdout) fclose(g_out);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
在新工单中引用
屏蔽一个用户