On Fri, Nov 8, 2019 at 9:08 AM André Eriksson <ean...@gmail.com> wrote: > > That works in simple cases, but does not work when the expression is an > untyped constant, like 1 or nil. In the case of 1 the variable will get a > concrete type of int, while fn may accept a float32, or even a private type > that cannot be named in the current package.
You might want to look at the rewriting that cmd/cgo does, as it handles this exact kind of case. Basically, for untyped constants, you know the desired type, because it's in the function signature. So use that. It does get kind of complicated, though. Ian > On Friday, November 8, 2019 at 5:51:10 PM UTC+1, Michael Jones wrote: >> >> If expr was evaluable in the original code then why not rewrite in place >> after assigning temporaries? >> >> go fn(e1,e2) >> >> { >> t1,t2 := e1,e2 >> go func() { >> defer instrument() >> fn(t1,t2) >> } >> >> >> On Fri, Nov 8, 2019 at 8:38 AM André Eriksson <ean...@gmail.com> wrote: >>> >>> I am working on a type of Go preprocessor that rewrites source code to add >>> additional instrumentation to certain types of statements. >>> >>> One such statement is the go statement. I would like to instrument the >>> newly created goroutine, injecting some instrumentation code at the start >>> and finish of the goroutine. >>> >>> In the simple case, the rewrite is straightforward: >>> >>> go fn() >>> >>> becomes >>> >>> go func() { >>> defer instrument()() >>> fn() >>> }() >>> >>> However this approach does not work when fn takes parameters. >>> If we were to rewrite go fn(expr) into the equivalent form above: >>> >>> go func() { >>> defer instrument()() >>> fn(expr) >>> }() >>> >>> >>> the semantics change, since in the rewrite expr gets evaluated inside the >>> newly created goroutine, which can change the behavior and introduce data >>> races. >>> >>> My attempts to address this have not been particularly fruitful. >>> >>> One cannot pass in expr as an argument to the closure, because the type of >>> the expression may not have a valid name in the current package (for >>> example if expr evaluates to a private type in some other package). >>> >>> Similarly, if expr is a constant expression (like 1 or nil) the type may >>> depend on the corresponding parameter in fn’s signature. >>> >>> The only semantics-preserving rewrite I can think of revolves around using >>> package reflect, and rewriting like so: >>> >>> go func(fn reflect.Value, vals …reflect.Value) { >>> defer instrument() >>> fn.Call(vals) >>> }(reflect.ValueOf(fn), reflect.ValueOf(expr)) >>> >>> As far as I understand, this should be semantics-preserving, although with >>> a slight performance cost. (Though I imagine the cost of a reflection-based >>> call is dwarfed by the cost of spawning a goroutine.) >>> >>> Unfortunately this also comes with a major downside: the rewritten code >>> does not typecheck identically to the original code. Ideally I would like >>> the rewritten form to cause identical typechecking failures to the old >>> code, so that these errors are caught at compile time without requiring a >>> separate typechecking pass for the original code. >>> >>> Am I correct in the above reasoning? Can anyone think of a way to do this >>> sort of rewrite in a semantics-preserving and typechecking-preserving way? >>> >>> -- >>> You received this message because you are subscribed to the Google Groups >>> "golang-nuts" group. >>> To unsubscribe from this group and stop receiving emails from it, send an >>> email to golan...@googlegroups.com. >>> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/golang-nuts/a92641f3-2eda-4d4a-ab02-d2b40e3bde75%40googlegroups.com. >> >> >> >> -- >> Michael T. Jones >> michae...@gmail.com > > -- > You received this message because you are subscribed to the Google Groups > "golang-nuts" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to golang-nuts+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/ec41a345-163f-4a8a-a24f-b868def081a0%40googlegroups.com. -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAOyqgcWAjqU8dFfkNpMKyzTvUAcEkc0DjRnLJesWN9TsWjCs0A%40mail.gmail.com.