Interception messages in Squeak - reflection

I am trying to understand better reflection in Smalltalk. I am using the latest version of Squeak (v4.3). I want to intercept every message sent to instances of one of my classes. I assumed that I could override the method ProtoObject>>withArgs:executeMethod but Stéphane Ducasse explained me that for performance reason, this method is not used (this is my own summary of his answer). Which method should I override / how could intercept sent messages?
Here is the code of my attempt:
Object subclass: #C
instanceVariableNames: 'i'
classVariableNames: ''
poolDictionaries: ''
category: 'CSE3009'.
C class compile: 'newWithi: anInt
^(self new) i: anInt ; yourself.'.
C compile: 'withArgs: someArgs executeMethod: aMethod
Transcript show: ''Caught: ''.
^ super withArgs: someArgs executeMethod aMethod.'.
C compile: 'foo: aText
Transcript show: aText.
Transcript show: i.
Transcript cr.'.
C compile: 'i: anInt
i := anInt.'.
o := C newWithi: 42.
o foo: 'This is foo: '.
Executing this entire piece of code yields:
This is foo: 42
When I would like to have:
Caught: This is foo: 42

There's no build-in way to intercept messages to objects like that. There are two ways we commonly use to do this kind of trick.
First, you can create a wrapper object which responds to doesNotUnderstand:. This object usually has nil for the superclass so it doesn't inherit any instance methods from Object. The doesNotUnderstand: handler would delegate all its messages to the target object. It has the option of performing code before and after the call. All references to the original object would now point to the new "proxy" object. Messages to self wouldn't be intercepted and the proxy would need to test for objects that return self and change the returned object to be the proxy instead.
The second approach is to use a mechanism called Method Wrappers. Method Wrappers allows you to replace all of the methods in a set of classes with methods that do some other operations before and after calling the original method. This approach can provide fairly seemless results and intercepts all messages including those send to self.
MethodWrappers is available for VisualWorks and VASmalltalk. I believe it's also available for Squeak and Pharo but I'm not positive.

The three main techniques are:
Dynamic proxies
Method wrapper
Bytecode instrumentation
For a good comparision of all possible approaches, have a look at "Evaluating Message Passing Control Techniques in Smalltalk" by Stephane Ducasse (you already know him, apparently).
Of interest is also "Smalltalk: A Reflective Langauge" by F. Rivard, that shows how to implement pre- and post-conditions using bytecode rewriting. This is also a form of interception.

Related

Why does my interface not contain a value if I explicitly "associated"

Hey guys this code is part of a mock client, mock server interaction. I am having trouble understanding context.
Here I explicitly "associate" my tracker interface with context using 'WithValue' and then inject it into my request using WithContext. But when I check if my request's context contains the tracker interface I am returned the error "This context should contain a tracker" . What is it about context and WithValue that I am just not understanding?
var tracker Tracker
ctx := context.WithValue(context.Background(), contextKey, tracker)
req := httptest.NewRequest("GET", "localhost:12345/test", nil)
req.Header.Add(HEADER)
req = req.WithContext(ctx)
_, ok := ctx.Value(contextKey).(Tracker)
if !ok {
log.Fatal("1: This context should contain a tracker")
}
Tracker is an interface, and it's not set to anything, so it's nil. So, it can't change nil to a Tracker, so it fails.
https://play.golang.org/p/4-KQXlCR8vD
The problem isn't that tracker is nil, the problem is that it doesn't contain a value of a concrete type that implements Tracker. The value of tracker could be nil, and this would work, but it has to be a "typed" nil.
The type assertion fails, because type assertions and type switches only work when the instance being asserted has a concrete type. A value can be of a concrete type by declaration , assignment, type assertion , or a type switch case.
When you do the type assertion ctx.Value(contextKey).(Tracker)
There's (conceptually) a 2-step process to this:
Determine the ctx.Value(contextKey)'s concrete type.
Determine whether that concrete type implements Tracker.
Here's a playground example that hopefully illustrates this better: https://play.golang.org/p/ojYzLObkisd
The DoAny() function in there is emulating what is happening when you put your tracker into context and then try to retrieve it with the type assertion.
I know this is just a basic example, but it's not very good practice to use var something SomeInterfaceType, even if you do assign it a value. You should use concrete types for that. Or even better, just use type inference, and you won't have to worry about it. For example:
type Foo interface {
DoFoo() string
}
type MyFoo struct {}
func (f *MyFoo) DoFoo() string {
return "some foo value"
}
// not so good
var f Foo = new(MyFoo)
// good
var f *MyFoo = new(MyFoo)
// better
f := new(MyFoo)
This leverages the fact that interfaces are implicit in Go, and leads to much more obvious and maintainable code, especially in larger projects. Declaring a variable with an interface type is essentially making your variable poloymorphic, but the real power of interfaces isn't polymorphism. The real power is in using them as "functional requirements" for your package's exposed functions/methods. One rule that illustrates this really well is "Accept interfaces, return structs".
EDIT:
I've edited my original answer to correct some mistakes and make some improvements. I also would like to answer a follow-up question from the OP:
what I did not understand is that unless you have an object that utilizes that tracker's methods your interface is nil. Is this correct thinking?
I think what you're trying to say is correct, but the words used aren't quite right. First, there are no objects in Go, as it is not object-oriented. Where in OOP languages, objects hold instances of types, Go uses variables and constants to hold instances of types. So the concept exists, but not by the same name. So your tracker variable will be an instance of a type that satisfies your Tracker interface, but its value with be nil unless you assign it a non-nil instance of a type that satisfies the Tracker interface.

Pointers sent to function

I have following code in main():
msgs, err := ch.Consume(
q.Name, // queue
//..
)
cache := ttlru.New(100, ttlru.WithTTL(5 * time.Minute)) //Cache type
//log.Println(reflect.TypeOf(msgs)) 'chan amqp.Delivery'
go func() {
//here I use `cache` and `msgs` as closures. And it works fine.
}
I decided to create separate function for instead of anonymous.
I declared it as func hitCache(cache *ttlru.Cache, msgs *chan amqp.Delivery) {
I get compile exception:
./go_server.go:61: cannot use cache (type ttlru.Cache) as type *ttlru.Cache in argument to hitCache:
*ttlru.Cache is pointer to interface, not interface
./go_server.go:61: cannot use msgs (type <-chan amqp.Delivery) as type *chan amqp.Delivery in argument to hitCache
Question: How should I pass msg and cache into the new function?
Well, if the receiving variable or a function parameter expects a value
of type *T — that is, "a pointer to T",
and you have a variable of type T, to get a pointer to it,
you have to get the address of that variable.
That's because "a pointer" is a value holding an address.
The address-taking operator in Go is &, so you need something like
hitCache(&cache, &msgs)
But note that some types have so-called "reference semantics".
That is, values of them keep references to some "hidden" data structure.
That means when you copy such values, you're copying references which all reference the same data structure.
In Go, the built-in types maps, slices and channels have reference semantics,
and hence you almost never need to pass around pointers to the values of such types (well, sometimes it can be useful but not now).
Interfaces can be thought of to have reference semantics, too (let's not for now digress into discussing this) because each value of any interface type contains two pointers.
So, in your case it's better to merely not declare the formal parameters of your function as pointers — declare them as "plain" types and be done with it.
All in all, you should definitely complete some basic resource on Go which explains these basic matters in more detail and more extensively.
You're using pointers in the function signature but not passing pointers - which is fine; as noted in the comments, there is no reason to use pointers for interface or channel values. Just change the function signature to:
hitCache(cache ttlru.Cache, msgs chan amqp.Delivery)
And it should work fine.
Pointers to interfaces are nearly never used. You may simplify things and use interfaces of pass by value.

Smalltalk: right way for custom construction

What book best describes right way to make custom constructors ?
For example, I want special file system (emulatied in RDBMS storage).
Object subclass: #C1_Object
C1_Object subclass: #C1_File
instanceVariableNames: 'stream name'
Use case:
C1_File new: 'blablabla'
or
C1_File create: 'blablabla'
(1) looks native, but
I have seen recommends don't override system allocation mechanics.
Next step: what is better
C1_File class>>create: aFileName
^ self new initialize: aFileName
C1_File>>initialize: aFileName
name := aFileName.
stream := C1_FileStream forceNewFileNamed: aFileName.
or
C1_File class>>create: aFileName
| instance |
instance := super new.
instance name: aFileName.
instance stream: ( C1_FileStream forceNewFileNamed: aFileName ).
^ instance initialize
C1_File>>initialize
^ super initialize
What book best describes right way to make custom constructors ?
Kent Beck's Smalltalk Best Practice Patterns (which I highly recommend to keep at hand for reference) contains around 100 Smalltalk patterns, among which is also
Constructor Method
Constructor Parameter Method
Shortcut Constructor Method
All of them discuss various aspects of object creation and parameter passing, however the common theme is increased understanding and clarity (and intention revealing selectors, which is another pattern).
When you have
C1_File create: 'blablabla'
it is not clear what is actually going to happen; is C1_File going to create blablabla? What would that mean? As Esteban pointed out, it is better to name the argument... C1_File named: 'blablabla'; now I know what is going to happen.
(1) looks native, but I have seen recommends don't override system allocation mechanics.
You would have to mess with #basicNew to mess with allocation mechanics. If you look at implementation of #new, it actually doesn't do much.
Behavior>>new
^ self basicNew initialize
There also plenty of examples in the system:
OrderedCollection with: anItem
Color fromString: '#AC13D9' or Color r: 0.2 g: 0.5 b: 0.1
Point x: 10 y: 17
Readers/Writers often use on:.. STONReader on: aReadStream
Note that the book mentioned in the beginning doesn't just show how to create a basic constructor, but also discusses other problems and challenges of the instance creation itself (e.g. when you have multiple different constructors to not blow up you method protocol, etc.)
Class-side vs instance-side - more of an addendum for Esteban's answer:
Keep the amount of regular behavior on the class-side to minimum; the class-side is primarily for meta-behavior --- managing the class itself, not doing the actual work.
who tell you not to override system allocation mechanisms?
In any case, override #new: is not recommended in this case because for convention #new: with a parameter receives a size, not a string, so it will be confusing.
Now, I would use something like: named:, newWithName:, etc. but that's up to you (is a preference matter).
One thing: in Pharo, if you do instance := self new and later instance initialize you will be calling initialize twice because the default implementation of #new is self basicNew initialize, so your method needs to be defined like this:
C1_File class>>create: aFileName
| instance |
instance := self basicNew.
instance name: aFileName.
instance stream: ( C1_FileStream forceNewFileNamed: aFileName ).
^ instance initialize
But I also wouldn't recommend doing like that (initialise the stream in a creator method does not feels good). Instead I would do:
C1_File class>>create: aFileName
^ self basicNew
initializeName: aFileName;
yourself.
C1_File>>initializeName: aFileName
self name: aFileName.
self stream: ( C1_FileStream forceNewFileNamed: aFileName ).
self initialize.
I do not have a reference from the top of my head other than Smalltalk code I have seen in Sqeuak and third-party packages. Custom constructors like Read-/WriteStream class>>on: aCollection, Text class>>fromString: communicate in a way what their arguments will be used for in the created instance. Another style is to name the constructor directly after the instance variables that are initialized by it. Something like Point class>>x:y:. The Collection constructors with: and withAll: make the code read fluently.
I would always strive to name constructors such that it becomes clear for the reader of a send, what you will get as an answer (a Stream that operates on that collection, a Point with these coordinates, an opened File with the given name/path?). I would not override new:, and create sounds rather generic, but could be useful when talking about files (open for writing or create if it does not exist), though that differs from the FileStream API, as far as I know.
Otherwise, there is still the possibility to not define a constructors, but initialize the object with accessors etc. directly following the new:
MyFileDoesNotExist new
file: c1File;
yourself "or signal in this case"

Kotlin: How are a Delegate's get- and setValue Methods accessed?

I've been wondering how delegated properties ("by"-Keyword) work under-the-hood. I get that by contract the delegate (right side of "by") has to implement a get and setValue(...) method, but how can that be ensured by the compiler and how can those methods be accessed at runtime? My initial thought was that obviously the delegates must me implementing some sort of "SuperDelegate"-Interface, but it appears that is not the case. So the only option left (that I am aware of) would be to use Reflection to access those methods, possibly implemented at a low level inside the language itself. I find that to be somewhat weird, since by my understanding that would be rather inefficient. Also the Reflection API is not even part of the stdlib, which makes it even weirder.
I am assuming that the latter is already (part of) the answer. So let me furthermore ask you the following: Why is there no SuperDelegate-Interface that declare the getter and setter methods that we are forced to use anyway? Wouldn't that be much cleaner?
The following is not essential to the question
The described Interface(s) are even already defined in ReadOnlyProperty and ReadWriteProperty. To decide which one to use could then be made dependable on whether we have a val/var. Or even omit that since calling the setValue Method on val's is being prevented by the compiler and only use the ReadWriteProperty-Interface as the SuperDelegate.
Arguably when requiring a delegate to implement a certain interface the construct would be less flexible. Though that would be assuming that the Class used as a Delegate is possibly unaware of being used as such, which I find to be unlikely given the specific requirements for the necessary methods. And if you still insist, here's a crazy thought: Why not even go as far as to make that class implement the required interface via Extension (I'm aware that's not possible as of now, but heck, why not? Probably there's a good 'why not', please let me know as a side-note).
The delegates convention (getValue + setValue) is implemented at the compiler side and basically none of its resolution logic is executed at runtime: the calls to the corresponding methods of a delegate object are placed directly in the generated bytecode.
Let's take a look at the bytecode generated for a class with a delegated property (you can do that with the bytecode viewing tool built into IntelliJ IDEA):
class C {
val x by lazy { 123 }
}
We can find the following in the generated bytecode:
This is the field of the class C that stores the reference to the delegate object:
// access flags 0x12
private final Lkotlin/Lazy; x$delegate
This is the part of the constructor (<init>) that initialized the delegate field, passing the function to the Lazy constructor:
ALOAD 0
GETSTATIC C$x$2.INSTANCE : LC$x$2;
CHECKCAST kotlin/jvm/functions/Function0
INVOKESTATIC kotlin/LazyKt.lazy (Lkotlin/jvm/functions/Function0;)Lkotlin/Lazy;
PUTFIELD C.x$delegate : Lkotlin/Lazy;
And this is the code of getX():
L0
ALOAD 0
GETFIELD C.x$delegate : Lkotlin/Lazy;
ASTORE 1
ALOAD 0
ASTORE 2
GETSTATIC C.$$delegatedProperties : [Lkotlin/reflect/KProperty;
ICONST_0
AALOAD
ASTORE 3
L1
ALOAD 1
INVOKEINTERFACE kotlin/Lazy.getValue ()Ljava/lang/Object;
L2
CHECKCAST java/lang/Number
INVOKEVIRTUAL java/lang/Number.intValue ()I
IRETURN
You can see the call to the getValue method of Lazy that is placed directly in the bytecode. In fact, the compiler resolves the method with the correct signature for the delegate convention and generates the getter that calls that method.
This convention is not the only one implemented at the compiler side: there are also iterator, compareTo, invoke and the other operators that can be overloaded -- all of them are similar, but the code generation logic for them is simpler than that of delegates.
Note, however, that none of them requires an interface to be implemented: the compareTo operator can be defined for a type not implementing Comparable<T>, and iterator() does not require the type to be an implementation of Iterable<T>, they are anyway resolved at compile-time.
While the interfaces approach could be cleaner than the operators convention, it would allow less flexibility: for example, extension functions could not be used because they cannot be compiled into methods overriding those of an interface.
If you look at the generated Kotlin bytecode, you'll see that a private field is created in the class holding the delegate you're using, and the get and set method for the property just call the corresponding method on that delegate field.
As the class of the delegate is known at compile time, no reflection has to happen, just simple method calls.

Find all imported interfaces that object supports

I have an object like os.Stdout and I want to know if it supports io.WriteCloser on my platform. I can get the type of my object, but it doesn't tell me anything about interfaces.
package main
import ("fmt"; "reflect"; "os")
func main() {
fmt.Println(reflect.TypeOf(os.Stdout))
}
This code prints *os.File to console.
I can manually lookup if os.File matches io.WriteCloser methods, but I am curious to get all interfaces that this object supports.
It's not an exactly answer on the question, because it is not for runtime. Anyway I think it maybe useful
Take a look on https://golang.org/lib/godoc/analysis/help.html
godoc has static analysis features. And it can display your type implements relations.
For example you can run godoc -http=:8081 -analysis=type and get all your packages documentation with type analysis.
To expand on the comment from #Volker regarding type assertions, that would look like this:
_, implements := interface{}(os.Stdout).(io.Reader)
It casts os.Stdout to an interface{} type and then attempts to assert that it is an io.Reader. Type assertions return two values; the first is the asserted value (or nil if assertion fails) and the second is a boolean indicating if the assertion was successful or not. If you omit capturing the second return value then a failed assertion will cause a panic.
For alternative, possibly more generic or runtime requirements the types package may have some useful functions based on reflection: https://godoc.org/golang.org/x/tools/go/types

Resources