[Go] Add goargout typemap.

This commit is contained in:
Ian Lance Taylor 2014-09-09 11:28:04 -07:00
commit acaaa0f31f
6 changed files with 286 additions and 44 deletions

View file

@ -868,6 +868,7 @@ private:
Swig_typemap_attach_parms("default", parms, dummy);
Swig_typemap_attach_parms("gotype", parms, dummy);
Swig_typemap_attach_parms("goin", parms, dummy);
Swig_typemap_attach_parms("goargout", parms, dummy);
Swig_typemap_attach_parms("imtype", parms, dummy);
int parm_count = emit_num_arguments(parms);
int required_count = emit_num_required(parms);
@ -892,20 +893,25 @@ private:
bool needs_wrapper = (gccgo_flag || receiver || is_constructor || is_destructor || parm_count > required_count);
bool has_goout = false;
if (goout) {
has_goout = true;
}
// See whether any of the function parameters are represented by
// interface values. When calling the C++ code, we need to convert
// back to a uintptr.
if (!needs_wrapper) {
Parm *p = parms;
for (int i = 0; i < parm_count; ++i) {
p = getParm(p);
String *ty = Getattr(p, "type");
if (goTypeIsInterface(p, ty) || Getattr(p, "tmap:goin") != NULL) {
needs_wrapper = true;
break;
}
p = nextParm(p);
Parm *p = parms;
for (int i = 0; i < parm_count; ++i) {
p = getParm(p);
String *ty = Getattr(p, "type");
if (Getattr(p, "tmap:goargout")) {
has_goout = true;
needs_wrapper = true;
} else if (goTypeIsInterface(p, ty) || Getattr(p, "tmap:goin")) {
needs_wrapper = true;
}
p = nextParm(p);
}
if (goTypeIsInterface(n, result) || goout != NULL) {
needs_wrapper = true;
@ -982,7 +988,7 @@ private:
Printv(f_go_wrappers, "func ", NULL);
Parm *p = parms;
p = parms;
int pi = 0;
// Add the receiver if this is a method.
@ -1097,7 +1103,7 @@ private:
}
if (gccgo_flag) {
if (goout != NULL || is_constructor) {
if (has_goout || is_constructor) {
Printv(call, "\tfunc() {\n", NULL);
}
Printv(call, "\tdefer SwigCgocallDone()\n", NULL);
@ -1143,6 +1149,7 @@ private:
if ((i == 0 && is_destructor) || ((i > 0 || !receiver || base || is_constructor) && goTypeIsInterface(p, pt))) {
Printv(call, ".Swigcptr()", NULL);
}
Setattr(p, "emit:goinput", ln);
} else {
String *ivar = NewString("");
Printf(ivar, "_swig_i_%d", i);
@ -1154,19 +1161,22 @@ private:
Printv(f_go_wrappers, goin, NULL);
Delete(goin);
Printv(call, ivar, NULL);
Setattr(p, "emit:goinput", ivar);
}
p = nextParm(p);
}
Printv(call, ")\n", NULL);
if (gccgo_flag && (goout != NULL || is_constructor)) {
if (gccgo_flag && (has_goout || is_constructor)) {
Printv(call, "\t}()\n", NULL);
}
Printv(f_go_wrappers, call, NULL);
Delete(call);
goargout(parms, parm_count);
if (need_return_var) {
if (goout == NULL) {
Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
@ -1676,6 +1686,32 @@ private:
}
}
/* -----------------------------------------------------------------------
* goargout()
*
* Handle Go argument output code if any. This is used for the Go
* function. This assumes that each parameter has an "emit:goinput"
* property with the name to use to refer to that parameter.
* ----------------------------------------------------------------------- */
void goargout(ParmList *parms, int parm_count) {
Parm *p = parms;
for (int i = 0; i < parm_count; ++i) {
p = getParm(p);
String *tm = Getattr(p, "tmap:goargout");
if (!tm) {
p = nextSibling(p);
} else {
tm = Copy(tm);
Replaceall(tm, "$result", "swig_r");
Replaceall(tm, "$input", Getattr(p, "emit:goinput"));
Printv(f_go_wrappers, tm, NULL);
Delete(tm);
p = Getattr(p, "tmap:goargout:next");
}
}
}
/* -----------------------------------------------------------------------
* freearg()
*
@ -3170,6 +3206,7 @@ private:
Swig_typemap_attach_parms("directorargout", parms, w);
Swig_typemap_attach_parms("godirectorin", parms, w);
Swig_typemap_attach_parms("goin", parms, dummy);
Swig_typemap_attach_parms("goargout", parms, dummy);
if (!is_ignored) {
// We use an interface to see if this method is defined in Go.
@ -3282,16 +3319,29 @@ private:
if (GetFlag(n, "abstract")) {
Printv(f_go_wrappers, "\tpanic(\"call to pure virtual method\")\n", NULL);
} else {
bool has_goout = false;
String *goout = NULL;
if (SwigType_type(result) != T_VOID) {
Printv(f_go_wrappers, "\tvar swig_r ", goImType(n, result), "\n", NULL);
goout = Swig_typemap_lookup("goout", n, "swig_r", NULL);
if (goout) {
has_goout = true;
}
}
p = parms;
for (int i = 0; i < parm_count; ++i) {
p = getParm(p);
if (Getattr(p, "tmap:goargout")) {
has_goout = true;
}
p = nextParm(p);
}
String *call = NewString("");
if (gccgo_flag) {
if (goout != NULL) {
if (has_goout) {
Printv(call, "\tfunc() {\n", NULL);
}
Printv(call, "\tdefer SwigCgocallDone()\n", NULL);
@ -3320,6 +3370,7 @@ private:
if (goTypeIsInterface(p, pt)) {
Printv(call, ".Swigcptr()", NULL);
}
Setattr(p, "emit:goinput", ln);
} else {
String *ivar = NewString("");
Printf(ivar, "_swig_i_%d", i);
@ -3331,7 +3382,7 @@ private:
Printv(f_go_wrappers, goin, NULL);
Delete(goin);
Printv(call, ivar, NULL);
Delete(ivar);
Setattr(p, "emit:goinput", ivar);
}
p = nextParm(p);
@ -3339,13 +3390,15 @@ private:
Printv(call, ")\n", NULL);
if (gccgo_flag && goout != NULL) {
if (gccgo_flag && has_goout) {
Printv(call, "\t}()\n", NULL);
}
Printv(f_go_wrappers, call, NULL);
Delete(call);
goargout(parms, parm_count);
if (SwigType_type(result) != T_VOID) {
if (goout == NULL) {
Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
@ -3526,6 +3579,7 @@ private:
String *goin = Getattr(p, "tmap:goin");
if (goin == NULL) {
Printv(call, ln, NULL);
Setattr(p, "emit:goinput", ln);
} else {
String *ivar = NewString("");
Printf(ivar, "_swig_i_%d", i);
@ -3537,7 +3591,7 @@ private:
Printv(f_go_wrappers, goin, NULL);
Delete(goin);
Printv(call, ivar, NULL);
Delete(ivar);
Setattr(p, "emit:goinput", ivar);
}
Delete(ln);
@ -3554,6 +3608,8 @@ private:
Printv(f_go_wrappers, call, NULL);
Delete(call);
goargout(parms, parm_count);
if (SwigType_type(result) != T_VOID) {
if (goout == NULL) {
Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
@ -3838,6 +3894,21 @@ private:
Printv(w->code, " crosscall2(", callback_wname, ", &swig_a, (int) sizeof swig_a);\n", NULL);
/* Marshal outputs */
for (p = parms; p;) {
String *tm;
if ((tm = Getattr(p, "tmap:directorargout"))) {
tm = Copy(tm);
Replaceall(tm, "$result", "jresult");
Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
Printv(w->code, tm, "\n", NIL);
Delete(tm);
p = Getattr(p, "tmap:directorargout:next");
} else {
p = nextSibling(p);
}
}
if (SwigType_type(result) != T_VOID) {
String *result_str = NewString("c_result");
String *tm = Swig_typemap_lookup("directorout", n, result_str, NULL);
@ -3886,7 +3957,7 @@ private:
String *pn = NewString("g");
Append(pn, Getattr(p, "lname"));
Setattr(p, "emit:input", pn);
Setattr(p, "emit:directorinput", pn);
String *tm = gccgoCTypeForGoValue(n, Getattr(p, "type"), pn);
Wrapper_add_local(w, pn, tm);
@ -3915,6 +3986,21 @@ private:
}
Printv(w->code, callback_wname, "(go_val", args, ");\n", NULL);
/* Marshal outputs */
for (p = parms; p;) {
String *tm;
if ((tm = Getattr(p, "tmap:directorargout"))) {
tm = Copy(tm);
Replaceall(tm, "$result", "jresult");
Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
Printv(w->code, tm, "\n", NIL);
Delete(tm);
p = Getattr(p, "tmap:directorargout:next");
} else {
p = nextSibling(p);
}
}
if (SwigType_type(result) != T_VOID) {
String *result_str = NewString("c_result");
String *tm = Swig_typemap_lookup("directorout", n, result_str, NULL);
@ -3933,21 +4019,6 @@ private:
Delete(result_str);
}
}
/* Marshal outputs */
for (p = parms; p;) {
String *tm;
if ((tm = Getattr(p, "tmap:directorargout"))) {
tm = Copy(tm);
Replaceall(tm, "$result", "jresult");
Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
Printv(w->code, tm, "\n", NIL);
Delete(tm);
p = Getattr(p, "tmap:directorargout:next");
} else {
p = nextSibling(p);
}
}
} else {
assert(is_pure_virtual);
Printv(w->code, " _swig_gopanic(\"call to pure virtual function ", Getattr(parent, "sym:name"), name, "\");\n", NULL);
@ -4990,6 +5061,17 @@ private:
String *gcCTypeForGoValue(Node *n, SwigType *type, String *name) {
bool is_interface;
String *gt = goTypeWithInfo(n, type, true, &is_interface);
String *tail = NewString("");
SwigType *t = SwigType_typedef_resolve_all(type);
if (!SwigType_isreference(t)) {
while (Strncmp(gt, "*", 1) == 0) {
Replace(gt, "*", "", DOH_REPLACE_FIRST);
Printv(tail, "*", NULL);
}
}
Delete(t);
bool is_string = Strcmp(gt, "string") == 0;
bool is_slice = Strncmp(gt, "[]", 2) == 0;
bool is_function = Strcmp(gt, "_swig_fnptr") == 0;
@ -5017,18 +5099,21 @@ private:
if (is_string) {
// Note that we don't turn a reference to a string into a
// pointer to a string. Strings are immutable anyhow.
ret = NewString("_gostring_ ");
Append(ret, name);
ret = NewString("");
Printv(ret, "_gostring_", tail, " ", name, NULL);
Delete(tail);
return ret;
} else if (is_slice) {
// Slices are always passed as a _goslice_, whether or not references
// are involved.
ret = NewString("_goslice_ ");
Append(ret, name);
ret = NewString("");
Printv(ret, "_goslice_", tail, " ", name, NULL);
Delete(tail);
return ret;
} else if (is_function || is_member) {
ret = NewString("void *");
Append(ret, name);
ret = NewString("");
Printv(ret, "void*", tail, " ", name, NULL);
Delete(tail);
return ret;
} else if (is_complex64) {
ret = NewString("_Complex float ");
@ -5045,6 +5130,7 @@ private:
SwigType_add_pointer(t);
ret = SwigType_lstr(t, name);
Delete(t);
Delete(tail);
return ret;
} else {
SwigType *t = SwigType_typedef_resolve_all(type);
@ -5068,6 +5154,7 @@ private:
}
Delete(q);
Delete(t);
Delete(tail);
return ret;
}
}
@ -5100,14 +5187,17 @@ private:
} else if (is_float64) {
ret = NewString("double ");
} else {
Delete(tail);
return SwigType_lstr(type, name);
}
}
Append(ret, tail);
if (SwigType_isreference(type)) {
Append(ret, "* ");
}
Append(ret, name);
Delete(tail);
return ret;
}