func (g *javaGen) genMethodInterfaceProxy(oName string, m *types.Func) { if !g.isSigSupported(m.Type()) { g.Printf("// skipped method %s with unsupported parameter or return types\n\n", oName) return } sig := m.Type().(*types.Signature) params := sig.Params() res := sig.Results() g.genInterfaceMethodSignature(m, oName, false) g.Indent() // Push a JNI reference frame with a conservative capacity of two for each per parameter (Seq.Ref and Seq.Object), // plus extra space for the receiver, the return value, and exception (if any). g.Printf("JNIEnv *env = go_seq_push_local_frame(%d);\n", 2*params.Len()+10) g.Printf("jobject o = go_seq_from_refnum(env, refnum, proxy_class_%s_%s, proxy_class_%s_%s_cons);\n", g.pkgPrefix, oName, g.pkgPrefix, oName) for i := 0; i < params.Len(); i++ { pn := paramName(params, i) g.genCToJava("_"+pn, pn, params.At(i).Type(), modeTransient) } if res.Len() > 0 && !isErrorType(res.At(0).Type()) { t := res.At(0).Type() g.Printf("%s res = (*env)->Call%sMethod(env, o, ", g.jniType(t), g.jniCallType(t)) } else { g.Printf("(*env)->CallVoidMethod(env, o, ") } g.Printf("mid_%s_%s", oName, m.Name()) for i := 0; i < params.Len(); i++ { g.Printf(", _%s", paramName(params, i)) } g.Printf(");\n") var retName string if res.Len() > 0 { var rets []string t := res.At(0).Type() if !isErrorType(t) { g.genJavaToC("res", t, modeRetained) retName = "_res" rets = append(rets, retName) } if res.Len() == 2 || isErrorType(t) { g.Printf("jstring exc = go_seq_get_exception_message(env);\n") st := types.Typ[types.String] g.genJavaToC("exc", st, modeRetained) retName = "_exc" rets = append(rets, "_exc") } if res.Len() > 1 { g.Printf("cproxy%s_%s_%s_return sres = {\n", g.pkgPrefix, oName, m.Name()) g.Printf(" %s\n", strings.Join(rets, ", ")) g.Printf("};\n") retName = "sres" } } g.Printf("go_seq_pop_local_frame(env);\n") if retName != "" { g.Printf("return %s;\n", retName) } g.Outdent() g.Printf("}\n\n") }
func (g *goGen) genFuncSignature(o *types.Func, objName string) { g.Printf("//export proxy%s_%s_%s\n", g.pkgPrefix, objName, o.Name()) g.Printf("func proxy%s_%s_%s(", g.pkgPrefix, objName, o.Name()) if objName != "" { g.Printf("refnum C.int32_t") } sig := o.Type().(*types.Signature) params := sig.Params() for i := 0; i < params.Len(); i++ { if objName != "" || i > 0 { g.Printf(", ") } p := params.At(i) g.Printf("param_%s C.%s", g.paramName(params, i), g.cgoType(p.Type())) } g.Printf(") ") res := sig.Results() if res.Len() > 0 { g.Printf("(") for i := 0; i < res.Len(); i++ { if i > 0 { g.Printf(", ") } g.Printf("C.%s", g.cgoType(res.At(i).Type())) } g.Printf(") ") } g.Printf("{\n") }
func (w *Walker) emitFunc(f *types.Func) { sig := f.Type().(*types.Signature) if sig.Recv() != nil { panic("method considered a regular function: " + f.String()) } w.emitf("func %s%s", f.Name(), w.signatureString(sig)) }
func (g *JavaGen) genConstructor(f *types.Func, n string, jcls bool) { g.Printf("public %s(", n) g.genFuncArgs(f, nil, false) g.Printf(") {\n") g.Indent() sig := f.Type().(*types.Signature) params := sig.Params() if jcls { g.Printf("super(") for i := 0; i < params.Len(); i++ { if i > 0 { g.Printf(", ") } g.Printf(g.paramName(params, i)) } g.Printf(");\n") } g.Printf("this.ref = ") g.Printf("__%s(", f.Name()) for i := 0; i < params.Len(); i++ { if i > 0 { g.Printf(", ") } g.Printf(g.paramName(params, i)) } g.Printf(");\n") g.Outdent() g.Printf("}\n\n") g.Printf("private static native Seq.Ref __%s(", f.Name()) g.genFuncArgs(f, nil, false) g.Printf(");\n\n") }
// identicalSansNames compares two functions to check if their types are identical // according to the names. e.g. // - It does not care if the names of the parameters or return values differ // - It does not care if the implementations of the types differ func identicalSansNames(fa, fb *types.Func) bool { // must always succeed sigA := fa.Type().(*types.Signature) sigB := fb.Type().(*types.Signature) var ( lenParams = sigA.Params().Len() lenResults = sigA.Results().Len() ) if sigB.Params().Len() != lenParams { return false } if sigB.Results().Len() != lenResults { return false } for i := 0; i < lenParams; i++ { if types.TypeString(sigA.Params().At(i).Type(), nil) != types.TypeString(sigB.Params().At(i).Type(), nil) { return false } } for i := 0; i < lenResults; i++ { if types.TypeString(sigA.Results().At(i).Type(), nil) != types.TypeString(sigB.Results().At(i).Type(), nil) { return false } } return true }
func (g *javaGen) genFunc(o *types.Func, method bool) { if err := g.funcSignature(o, !method); err != nil { g.errorf("%v", err) return } sig := o.Type().(*types.Signature) res := sig.Results() g.Printf(" {\n") g.Indent() g.Printf("go.Seq _in = null;\n") g.Printf("go.Seq _out = null;\n") returnsError := false var resultType types.Type if res.Len() > 0 { if !isErrorType(res.At(0).Type()) { resultType = res.At(0).Type() } if res.Len() > 1 || isErrorType(res.At(0).Type()) { returnsError = true } } if resultType != nil || returnsError { g.Printf("_out = new go.Seq();\n") } if resultType != nil { t := g.javaType(resultType) g.Printf("%s _result;\n", t) } params := sig.Params() if method || params.Len() > 0 { g.Printf("_in = new go.Seq();\n") } if method { g.Printf("_in.writeRef(ref);\n") } for i := 0; i < params.Len(); i++ { p := params.At(i) g.Printf("_in.write%s;\n", seqWrite(p.Type(), paramName(params, i))) } g.Printf("Seq.send(DESCRIPTOR, CALL_%s, _in, _out);\n", o.Name()) if resultType != nil { g.genRead("_result", "_out", resultType) } if returnsError { g.Printf(`String _err = _out.readString(); if (_err != null && !_err.isEmpty()) { throw new Exception(_err); } `) } if resultType != nil { g.Printf("return _result;\n") } g.Outdent() g.Printf("}\n\n") }
func GoProto(fn *types.Func) (string, string, string) { pkgname := "package " + fn.Pkg().Name() + "\n" imports := "" signature := fn.Type().(*types.Signature) sig := strings.TrimPrefix(signature.String(), "func(") fnproto := "func " + fn.Name() + "(" + sig + "\n" return pkgname, imports, fnproto }
func isCallable(t *types.Func) bool { // TODO(crawshaw): functions that are not implementable from // another language may still be callable (for example, a // returned value with an unexported type can be treated as // an opaque value by the caller). This restriction could be // lifted. return isImplementable(t.Type().(*types.Signature)) }
func (g *JavaGen) genMethodInterfaceProxy(oName string, m *types.Func) { if !g.isSigSupported(m.Type()) { g.Printf("// skipped method %s with unsupported parameter or return types\n\n", oName) return } sig := m.Type().(*types.Signature) params := sig.Params() res := sig.Results() g.genInterfaceMethodSignature(m, oName, false, g.paramName) g.Indent() g.Printf("JNIEnv *env = go_seq_push_local_frame(%d);\n", params.Len()) g.Printf("jobject o = go_seq_from_refnum(env, refnum, proxy_class_%s_%s, proxy_class_%s_%s_cons);\n", g.pkgPrefix, oName, g.pkgPrefix, oName) for i := 0; i < params.Len(); i++ { pn := g.paramName(params, i) g.genCToJava("_"+pn, pn, params.At(i).Type(), modeTransient) } if res.Len() > 0 && !isErrorType(res.At(0).Type()) { t := res.At(0).Type() g.Printf("%s res = (*env)->Call%sMethod(env, o, ", g.jniType(t), g.jniCallType(t)) } else { g.Printf("(*env)->CallVoidMethod(env, o, ") } g.Printf("mid_%s_%s", oName, m.Name()) for i := 0; i < params.Len(); i++ { g.Printf(", _%s", g.paramName(params, i)) } g.Printf(");\n") var retName string if res.Len() > 0 { var rets []string t := res.At(0).Type() if !isErrorType(t) { g.genJavaToC("res", t, modeRetained) retName = "_res" rets = append(rets, retName) } if res.Len() == 2 || isErrorType(t) { g.Printf("jobject exc = go_seq_get_exception(env);\n") errType := types.Universe.Lookup("error").Type() g.genJavaToC("exc", errType, modeRetained) retName = "_exc" rets = append(rets, "_exc") } if res.Len() > 1 { g.Printf("cproxy%s_%s_%s_return sres = {\n", g.pkgPrefix, oName, m.Name()) g.Printf(" %s\n", strings.Join(rets, ", ")) g.Printf("};\n") retName = "sres" } } g.Printf("go_seq_pop_local_frame(env);\n") if retName != "" { g.Printf("return %s;\n", retName) } g.Outdent() g.Printf("}\n\n") }
func (g *ObjcGen) genFuncH(obj *types.Func) { if !g.isSigSupported(obj.Type()) { g.Printf("// skipped function %s with unsupported parameter or return types\n\n", obj.Name()) return } if s := g.funcSummary(nil, obj); s != nil { g.Printf("FOUNDATION_EXPORT %s;\n", s.asFunc(g)) } }
func (g *JavaGen) genJNIFuncBody(o *types.Func, sName string, jm *java.Func, isjava bool) { sig := o.Type().(*types.Signature) res := sig.Results() if sName != "" { g.Printf("int32_t o = go_seq_to_refnum_go(env, __this__);\n") } params := sig.Params() first := 0 if isjava && params.Len() > 0 && params.At(0).Name() == "this" { // Start after the implicit this argument. first = 1 g.Printf("int32_t _%s = go_seq_to_refnum(env, __this__);\n", g.paramName(params, 0)) } for i := first; i < params.Len(); i++ { name := g.paramName(params, i) g.genJavaToC(name, params.At(i).Type(), modeTransient) } resPrefix := "" if res.Len() > 0 { if res.Len() == 1 { g.Printf("%s r0 = ", g.cgoType(res.At(0).Type())) } else { resPrefix = "res." g.Printf("struct proxy%s_%s_%s_return res = ", g.pkgPrefix, sName, o.Name()) } } g.Printf("proxy%s_%s_%s(", g.pkgPrefix, sName, o.Name()) if sName != "" { g.Printf("o") } // Pass all arguments, including the implicit this argument. for i := 0; i < params.Len(); i++ { if i > 0 || sName != "" { g.Printf(", ") } g.Printf("_%s", g.paramName(params, i)) } g.Printf(");\n") for i := first; i < params.Len(); i++ { g.genRelease(g.paramName(params, i), params.At(i).Type(), modeTransient) } for i := 0; i < res.Len(); i++ { tn := fmt.Sprintf("_r%d", i) t := res.At(i).Type() g.genCToJava(tn, fmt.Sprintf("%sr%d", resPrefix, i), t, modeRetained) } // Go backwards so that any exception is thrown before // the return. for i := res.Len() - 1; i >= 0; i-- { t := res.At(i).Type() if !isErrorType(t) { g.Printf("return _r%d;\n", i) } else { g.Printf("go_seq_maybe_throw_exception(env, _r%d);\n", i) } } }
func (b *Builder) addFunction(u types.Universe, useName *types.Name, in *tc.Func) *types.Type { name := tcFuncNameToName(in.String()) if useName != nil { name = *useName } out := u.Function(name) out.Kind = types.DeclarationOf out.Underlying = b.walkType(u, nil, in.Type()) return out }
func (g *goGen) genFunc(o *types.Func) { if !g.isSigSupported(o.Type()) { g.Printf("// skipped function %s with unsupported parameter or result types\n", o.Name()) return } g.genFuncSignature(o, "") g.Indent() g.genFuncBody(o, g.pkgName(g.Pkg)) g.Outdent() g.Printf("}\n\n") }
func (p *printer) printFunc(recvType types.Type, obj *types.Func) { p.print("func ") sig := obj.Type().(*types.Signature) if recvType != nil { p.print("(") p.writeType(p.pkg, recvType) p.print(") ") } p.print(obj.Name()) p.writeSignature(p.pkg, sig) }
func (g *javaGen) genFuncSignature(o *types.Func, static, header bool) { sig := o.Type().(*types.Signature) res := sig.Results() var returnsError bool var ret string switch res.Len() { case 2: if !isErrorType(res.At(1).Type()) { g.errorf("second result value must be of type error: %s", o) return } returnsError = true ret = g.javaType(res.At(0).Type()) case 1: if isErrorType(res.At(0).Type()) { returnsError = true ret = "void" } else { ret = g.javaType(res.At(0).Type()) } case 0: ret = "void" default: g.errorf("too many result values: %s", o) return } g.Printf("public ") if static { g.Printf("static ") } if !header { g.Printf("native ") } oName := o.Name() g.Printf("%s %s(", ret, oName) params := sig.Params() for i := 0; i < params.Len(); i++ { if i > 0 { g.Printf(", ") } v := sig.Params().At(i) name := paramName(params, i) jt := g.javaType(v.Type()) g.Printf("%s %s", jt, name) } g.Printf(")") if returnsError { g.Printf(" throws Exception") } g.Printf(";\n") }
func getParameters(ctx Ctx, fn *types.Func) []*ssaParam { signature := fn.Type().(*types.Signature) if signature.Recv() != nil { panic("methods unsupported (only functions are supported)") } var params []*ssaParam for i := 0; i < signature.Params().Len(); i++ { param := signature.Params().At(i) n := ssaParam{v: param, ctx: ctx} params = append(params, &n) } return params }
func getReturnVar(ctx Ctx, fn *types.Func) []*ssaRetVar { signature := fn.Type().(*types.Signature) if signature.Recv() != nil { panic("methods unsupported (only functions are supported)") } var results []*ssaRetVar for i := 0; i < signature.Results().Len(); i++ { ret := signature.Results().At(i) n := ssaRetVar{v: ret, ctx: ctx} results = append(results, &n) } return results }
func (g *JavaGen) genFuncSignature(o *types.Func, jm *java.Func, hasThis bool) { sig := o.Type().(*types.Signature) res := sig.Results() var returnsError bool var ret string switch res.Len() { case 2: if !isErrorType(res.At(1).Type()) { g.errorf("second result value must be of type error: %s", o) return } returnsError = true ret = g.javaType(res.At(0).Type()) case 1: if isErrorType(res.At(0).Type()) { returnsError = true ret = "void" } else { ret = g.javaType(res.At(0).Type()) } case 0: ret = "void" default: g.errorf("too many result values: %s", o) return } g.Printf("%s ", ret) if jm != nil { g.Printf(jm.Name) } else { g.Printf(javaNameReplacer(lowerFirst(o.Name()))) } g.Printf("(") g.genFuncArgs(o, jm, hasThis) g.Printf(")") if returnsError { if jm != nil { if jm.Throws == "" { g.errorf("%s declares an error return value but the overriden method does not throw", o) return } g.Printf(" throws %s", jm.Throws) } else { g.Printf(" throws Exception") } } g.Printf(";\n") }
func (g *goGen) genFuncBody(o *types.Func, selectorLHS string) { sig := o.Type().(*types.Signature) params := sig.Params() for i := 0; i < params.Len(); i++ { p := params.At(i) pn := "param_" + g.paramName(params, i) g.genRead("_"+pn, pn, p.Type(), modeTransient) } res := sig.Results() if res.Len() > 2 || res.Len() == 2 && !isErrorType(res.At(1).Type()) { g.errorf("functions and methods must return either zero or one values, and optionally an error") return } if res.Len() > 0 { for i := 0; i < res.Len(); i++ { if i > 0 { g.Printf(", ") } g.Printf("res_%d", i) } g.Printf(" := ") } g.Printf("%s%s(", selectorLHS, o.Name()) for i := 0; i < params.Len(); i++ { if i > 0 { g.Printf(", ") } g.Printf("_param_%s", g.paramName(params, i)) } g.Printf(")\n") for i := 0; i < res.Len(); i++ { pn := fmt.Sprintf("res_%d", i) g.genWrite("_"+pn, pn, res.At(i).Type(), modeRetained) } if res.Len() > 0 { g.Printf("return ") for i := 0; i < res.Len(); i++ { if i > 0 { g.Printf(", ") } g.Printf("_res_%d", i) } g.Printf("\n") } }
func (g *JavaGen) genJNIConstructor(f *types.Func, sName string) { if !g.isSigSupported(f.Type()) { return } sig := f.Type().(*types.Signature) res := sig.Results() g.Printf("JNIEXPORT jobject JNICALL\n") g.Printf("Java_%s_%s_%s(JNIEnv *env, jclass clazz", g.jniPkgName(), sName, java.JNIMangle("__"+f.Name())) params := sig.Params() for i := 0; i < params.Len(); i++ { v := params.At(i) jt := g.jniType(v.Type()) g.Printf(", %s %s", jt, g.paramName(params, i)) } g.Printf(") {\n") g.Indent() for i := 0; i < params.Len(); i++ { name := g.paramName(params, i) g.genJavaToC(name, params.At(i).Type(), modeTransient) } // Constructors always return a mandatory *T and an optional error if res.Len() == 1 { g.Printf("int32_t refnum = proxy%s__%s(", g.pkgPrefix, f.Name()) } else { g.Printf("struct proxy%s__%s_return res = proxy%s__%s(", g.pkgPrefix, f.Name(), g.pkgPrefix, f.Name()) } for i := 0; i < params.Len(); i++ { if i > 0 { g.Printf(", ") } g.Printf("_%s", g.paramName(params, i)) } g.Printf(");\n") for i := 0; i < params.Len(); i++ { g.genRelease(g.paramName(params, i), params.At(i).Type(), modeTransient) } // Extract multi returns and handle errors if res.Len() == 2 { g.Printf("int32_t refnum = res.r0;\n") g.genCToJava("_err", "res.r1", res.At(1).Type(), modeRetained) g.Printf("go_seq_maybe_throw_exception(env, _err);\n") } // Pass no proxy class so that the Seq.Ref is returned instead. g.Printf("return go_seq_from_refnum(env, refnum, NULL, NULL);\n") g.Outdent() g.Printf("}\n\n") }
func (p *exporter) method(m *types.Func) { sig := m.Type().(*types.Signature) if sig.Recv() == nil { log.Fatalf("gcimporter: method expected") } p.pos(m) p.string(m.Name()) if m.Name() != "_" && !ast.IsExported(m.Name()) { p.pkg(m.Pkg(), false) } // interface method; no need to encode receiver. p.paramList(sig.Params(), sig.Variadic()) p.paramList(sig.Results(), false) }
func (c *converter) convertFunc(v *gotypes.Func) *types.Func { if v == nil { return nil } if v, ok := c.converted[v]; ok { return v.(*types.Func) } ret := types.NewFunc( token.Pos(v.Pos()), c.ret, v.Name(), c.convertSignature(v.Type().(*gotypes.Signature)), ) c.converted[v] = ret return ret }
func (g *javaGen) genJNIFuncSignature(o *types.Func, sName string, proxy bool) { sig := o.Type().(*types.Signature) res := sig.Results() var ret string switch res.Len() { case 2: ret = g.jniType(res.At(0).Type()) case 1: if isErrorType(res.At(0).Type()) { ret = "void" } else { ret = g.jniType(res.At(0).Type()) } case 0: ret = "void" default: g.errorf("too many result values: %s", o) return } g.Printf("JNIEXPORT %s JNICALL\n", ret) g.Printf("Java_%s_%s", g.jniPkgName(), g.className()) if sName != "" { // 0024 is the mangled form of $, for naming inner classes. g.Printf("_00024") if proxy { g.Printf("proxy") } g.Printf("%s", sName) } g.Printf("_%s(JNIEnv* env, ", o.Name()) if sName != "" { g.Printf("jobject this") } else { g.Printf("jclass clazz") } params := sig.Params() for i := 0; i < params.Len(); i++ { g.Printf(", ") v := sig.Params().At(i) name := paramName(params, i) jt := g.jniType(v.Type()) g.Printf("%s %s", jt, name) } g.Printf(")") }
func (g *JavaGen) genJNIFunc(o *types.Func, sName string, jm *java.Func, proxy, isjava bool) { if !g.isSigSupported(o.Type()) { n := o.Name() if sName != "" { n = sName + "." + n } g.Printf("// skipped function %s with unsupported parameter or return types\n\n", n) return } g.genJNIFuncSignature(o, sName, jm, proxy, isjava) g.Printf(" {\n") g.Indent() g.genJNIFuncBody(o, sName, jm, isjava) g.Outdent() g.Printf("}\n\n") }
func (g *goGen) genFuncBody(o *types.Func, selectorLHS string) { sig := o.Type().(*types.Signature) params := sig.Params() for i := 0; i < params.Len(); i++ { p := params.At(i) g.genRead("param_"+paramName(params, i), "in", p.Type()) } res := sig.Results() if res.Len() > 2 || res.Len() == 2 && !isErrorType(res.At(1).Type()) { g.errorf("functions and methods must return either zero or one values, and optionally an error") return } returnsValue := false returnsError := false if res.Len() == 1 { if isErrorType(res.At(0).Type()) { returnsError = true g.Printf("err := ") } else { returnsValue = true g.Printf("res := ") } } else if res.Len() == 2 { returnsValue = true returnsError = true g.Printf("res, err := ") } g.Printf("%s.%s(", selectorLHS, o.Name()) for i := 0; i < params.Len(); i++ { if i > 0 { g.Printf(", ") } g.Printf("param_%s", paramName(params, i)) } g.Printf(")\n") if returnsValue { g.genWrite("res", "out", res.At(0).Type()) } if returnsError { g.genWrite("err", "out", res.At(res.Len()-1).Type()) } }
// genFuncArgs generated Java function arguments declaration for the function f. // If the supplied overridden java function is supplied, genFuncArgs omits the implicit // this argument. func (g *JavaGen) genFuncArgs(f *types.Func, jm *java.Func, hasThis bool) { sig := f.Type().(*types.Signature) params := sig.Params() first := 0 if hasThis { // Skip the implicit this argument to the Go method first = 1 } for i := first; i < params.Len(); i++ { if i > first { g.Printf(", ") } v := params.At(i) name := g.paramName(params, i) jt := g.javaType(v.Type()) g.Printf("%s %s", jt, name) } }
func checkFuncValue(t *testing.T, prog *ssa.Program, obj *types.Func) { fn := prog.FuncValue(obj) // fmt.Printf("FuncValue(%s) = %s\n", obj, fn) // debugging if fn == nil { if obj.Name() != "interfaceMethod" { t.Errorf("FuncValue(%s) == nil", obj) } return } if fnobj := fn.Object(); fnobj != obj { t.Errorf("FuncValue(%s).Object() == %s; value was %s", obj, fnobj, fn.Name()) return } if !types.Identical(fn.Type(), obj.Type()) { t.Errorf("FuncValue(%s).Type() == %s", obj, fn.Type()) return } }
// makeBound returns a bound method wrapper (or "bound"), a synthetic // function that delegates to a concrete or interface method denoted // by obj. The resulting function has no receiver, but has one free // variable which will be used as the method's receiver in the // tail-call. // // Use MakeClosure with such a wrapper to construct a bound method // closure. e.g.: // // type T int or: type T interface { meth() } // func (t T) meth() // var t T // f := t.meth // f() // calls t.meth() // // f is a closure of a synthetic wrapper defined as if by: // // f := func() { return t.meth() } // // Unlike makeWrapper, makeBound need perform no indirection or field // selections because that can be done before the closure is // constructed. // // EXCLUSIVE_LOCKS_ACQUIRED(meth.Prog.methodsMu) // func makeBound(prog *Program, obj *types.Func) *Function { prog.methodsMu.Lock() defer prog.methodsMu.Unlock() fn, ok := prog.bounds[obj] if !ok { description := fmt.Sprintf("bound method wrapper for %s", obj) if prog.mode&LogSource != 0 { defer logStack("%s", description)() } fn = &Function{ name: obj.Name() + "$bound", object: obj, Signature: changeRecv(obj.Type().(*types.Signature), nil), // drop receiver Synthetic: description, Prog: prog, pos: obj.Pos(), } fv := &FreeVar{name: "recv", typ: recvType(obj), parent: fn} fn.FreeVars = []*FreeVar{fv} fn.startBody() createParams(fn, 0) var c Call if !isInterface(recvType(obj)) { // concrete c.Call.Value = prog.declaredFunc(obj) c.Call.Args = []Value{fv} } else { c.Call.Value = fv c.Call.Method = obj } for _, arg := range fn.Params { c.Call.Args = append(c.Call.Args, arg) } emitTailCall(fn, &c) fn.finishBody() prog.bounds[obj] = fn } return fn }
// constructorType returns the type T for a function of the forms: // // func NewT...(...) *T // func NewT...(...) (*T, error) func (g *Generator) constructorType(f *types.Func) *types.TypeName { sig := f.Type().(*types.Signature) res := sig.Results() if res.Len() != 1 && !(res.Len() == 2 && isErrorType(res.At(1).Type())) { return nil } rt := res.At(0).Type() pt, ok := rt.(*types.Pointer) if !ok { return nil } nt, ok := pt.Elem().(*types.Named) if !ok { return nil } obj := nt.Obj() if !strings.HasPrefix(f.Name(), "New"+obj.Name()) { return nil } return obj }
func (g *generator) genInterfaceMethodSignature(m *types.Func, iName string, header bool) { sig := m.Type().(*types.Signature) params := sig.Params() res := sig.Results() if res.Len() == 0 { g.Printf("void ") } else { if res.Len() == 1 { g.Printf("%s ", g.cgoType(res.At(0).Type())) } else { if header { g.Printf("typedef struct cproxy%s_%s_%s_return {\n", g.pkgPrefix, iName, m.Name()) g.Indent() for i := 0; i < res.Len(); i++ { t := res.At(i).Type() g.Printf("%s r%d;\n", g.cgoType(t), i) } g.Outdent() g.Printf("} cproxy%s_%s_%s_return;\n", g.pkgPrefix, iName, m.Name()) } g.Printf("struct cproxy%s_%s_%s_return ", g.pkgPrefix, iName, m.Name()) } } g.Printf("cproxy%s_%s_%s(int32_t refnum", g.pkgPrefix, iName, m.Name()) for i := 0; i < params.Len(); i++ { t := params.At(i).Type() g.Printf(", %s %s", g.cgoType(t), paramName(params, i)) } g.Printf(")") if header { g.Printf(";\n") } else { g.Printf(" {\n") } }