A structure method is declared by:
(defstruct S
i: int32
m: (method int32 -> bool))
When we process the structure during symbol resolution, we add a placeholder entry into the symbol environment for an identifier named "S.m". Since '.' is illegal in identifiers, this cannot collide. That entry will point to the AST node for m: (method...), which is an at_methdecl node. In the type checker, this declaration will be given type ty_smethod. Note that the declaration in the structure does not declare the implicit this parameter, but the type checker will insert that parameter and type it as either (by-ref S) or S according to whether the structure S is a value or a reference type.
The method entry appearing within the structure is a declaration only. The method must be defined elsewhere by defining a function named S.m. This function must accept the initial this parameter explicitly.
If a method is called, then the first pass of the type checker will see an at_apply AST that looks like:
(s.m args...)
Because S.m is typed as ty_smethod, this AST will get rewritten to:
(S.m s args...)
which is a legal function call. Processing beyond that point will proceed exactly as if the S.m form had been given in the first place. That is: this structure methods are purely syntactic sugar.
Object methods are handled similarly to structure methods up to the back end. Given an object method
(defobject O
i: int32
m: (method int32 -> bool))
we similarly introduce a symbol O.m that points to the at_methdecl AST node. In the type checker, this declaration will be given type ty_omethod rather than ty_smethod. All of the ``magic'' happens in the back-end code generator, where we substitute a v-table indirect call and access the content reference pointer from the object, supplying that in place of the actual object pointer at the C level.
Also in contrast to structures, an object method should have no implementing procedure. There is an open issue about how to signal where the v-table should be emitted. This is a non-issue for the whole program compiler, but it is a potentially significant factor for any implementation that relies on dynamic linking.
The other difference between objects and structures concerns object construction. An object having methods m1...mn may be instantiated from any structure having compatible methods m1...mn. Compatibility is determined by type checking: the method type declared by the structure must subsume the method type declared in the object. That is: the object method must be instantiable at all points where it is declared.
However, no compatibility check is performed at the this pointer argument, because this compatibility requirement is satisfied structurally.
1.4.7