This is awful, dangerous, and compiler designers and writers will yell at you. Well done :)
I've always wanted a way to monkey-patch otherwise statically and well-bound code, but only for testing. In C, it's fairly easy to set up preprocessor rules to do so, though also litters your primary code with test specific stuff. I have mostly focused on how to integrate this into compiler logic; Building some functionality to replace specified symbols in the build phase. Simply replacing the function pointers in the runtime is brilliant, if more than a little hacky and prone to problems.
This is not monkey patching. This is the good old function/api "hooking" that's pretty common in the compiled language world: http://en.wikipedia.org/wiki/Hooking
Monkey patching is a less invasive version of hooking used in dynamic languages. Bottom line: if you are dealing with assembly it's no longer monkey patching :-)
Except the wiki page about monkey patching talks about it in the context of dynamic languages :-) It doesn't talk about C, C++ or other compiled languages.
Dynamic and compiled are not mutually exclusive. Objective-C is both a dynamic and compiled (to machine code) language that supports monkey patching. It supports extending classes with new methods and overriding existing methods in existing classes through its category feature.
This does have an unfortunate side effect though. Because Objective-C is a) compiled directly to machine code b) has no way of marking methods final and c) supports monkey patching, essentially no methods can be inlined by the compiler.
Of course, dynamic and compiled are not mutually exclusive. Go is not like Objective-C though and it doesn't support "Categories" or "extension methods" :)
I feel like I'm pretty familiar with "monkey patching" as practiced in Rubyland, and I'm a systems C programmer from the 90s. Can you help me understand the distinction you're drawing here? I don't have an understanding of "monkey patching" that involves how "invasive" it is; in fact, a repeated complaint about Ruby is how uninvasive it makes monkey patches, since the very concept of monkey patching breaks assumptions other programmers might rely on it.
I think the important distinction is that Ruby/Python monkey-patching work within the defined semantics of the language, whereas this is targeting implementation-specific details of one particular runtime.
At the end of the day however, it's still patching code you don't own. Doesn't the term strongly imply modifications outside the scope of the author's intentions? Even in ruby and python, monkey patching is rarely the documented means to modify a library's behavior.
Yes, monkey patching is pretty uninvasive. It's a better way to describe it. It's a "feature" supported by a dynamic language. Still, unexpected things can happen if something is patched multiple times though it's easy to track and fix :)
Monkey patching ends and hooking begins when you go outside of what's provided by the language digging into assembly and byte code.
Dynamic code loading is what makes C#/.net orm's fast (see Dapper, Destrier, PetaPOCO etc.) Basically they let you use an IL generator to emit a bunch of IL operations, then compile them to a delegate. This is useful specifically for creating the methods that take a data reader and turn discrete columns into fields on a database mapped object.
As soon as we can do this with Golang the orms we use will get much faster.
No, this is just a hack that is probably broken because the runtime doesn't know about the patched functions. The Go team are working on proper loadable modules.
Well, in the future the go runtime might require more detailed stack info other things to enable future things like concurrent garbage collection. Also, different implementations of Go have different requirements and calling conventions.
I've always wanted a way to monkey-patch otherwise statically and well-bound code, but only for testing. In C, it's fairly easy to set up preprocessor rules to do so, though also litters your primary code with test specific stuff. I have mostly focused on how to integrate this into compiler logic; Building some functionality to replace specified symbols in the build phase. Simply replacing the function pointers in the runtime is brilliant, if more than a little hacky and prone to problems.
I look forward to playing around with this.