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 golang-nuts+unsubscr...@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
> <https://groups.google.com/d/msgid/golang-nuts/a92641f3-2eda-4d4a-ab02-d2b40e3bde75%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>


-- 

*Michael T. jonesmichael.jo...@gmail.com <michael.jo...@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/CALoEmQx4n-PLJ_scPHfcqNtTnyCo2y1RG_enpV-Rqe4FtxwaQg%40mail.gmail.com.

Reply via email to