func (g *goGen) genFunc(o *types.Func) { g.Printf("func proxy_%s(out, in *seq.Buffer) {\n", o.Name()) g.Indent() g.genFuncBody(o, g.pkg.Name()) g.Outdent() g.Printf("}\n\n") }
func findMethod(prog *ssa.Program, meth *types.Func, typ types.Type, infer *TypeInfer) *ssa.Function { if meth != nil { return prog.LookupMethod(typ, meth.Pkg(), meth.Name()) } infer.Logger.Fatal(ErrMethodNotFound) return nil }
// 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 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 *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 (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 (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 *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 (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 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 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 (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 *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 getLocalDecls(ctx Ctx, fnDecl *ast.FuncDecl, fn *types.Func) []*ssaLocal { scope := fn.Scope() names := scope.Names() var locals []*ssaLocal for i := 0; i < len(names); i++ { name := names[i] obj := scope.Lookup(name) if isParam(ctx, fn, obj) { continue } node := ssaLocal{obj: obj, ctx: ctx} locals = append(locals, &node) } return locals }
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 *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 (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) }
// lookupMethod returns the method set for type typ, which may be one // of the interpreter's fake types. func lookupMethod(i *interpreter, typ types.Type, meth *types.Func) *ssa.Function { switch typ { case rtypeType: return i.rtypeMethods[meth.Id()] case errorType: return i.errorMethods[meth.Id()] } return i.prog.LookupMethod(typ, meth.Pkg(), meth.Name()) }
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 } }
// 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 *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") }
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 *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 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 (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") }