Files
tinygo/src/runtime/interface.go
T
2018-08-27 00:49:33 +02:00

60 lines
2.4 KiB
Go

package runtime
// This file implements Go interfaces.
//
// Interfaces are represented as a pair of {typecode, value}, where value can be
// anything (including non-pointers).
//
// Signatures itself are not matched on strings, but on uniqued numbers that
// contain the name and the signature of the function (to save space), think of
// signatures as interned strings at compile time.
//
// The typecode is a small number unique for the Go type. All typecodes <
// firstInterfaceNum do not have any methods and typecodes >= firstInterfaceNum
// all have at least one method. This means that methodSetRanges does not need
// to contain types without methods and is thus indexed starting at a typecode
// with number firstInterfaceNum.
//
// To further conserve some space, the methodSetRange (as the name indicates)
// doesn't contain a list of methods and function pointers directly, but instead
// just indexes into methodSetSignatures and methodSetFunctions which contains
// the mapping from uniqued signature to function pointer.
type _interface struct {
typecode uint16
value *uint8
}
// This struct indicates the range of methods in the methodSetSignatures and
// methodSetFunctions arrays that belong to this named type.
type methodSetRange struct {
index uint16 // start index into interfaceSignatures and interfaceFunctions
length uint16 // number of methods
}
// Global constants that will be set by the compiler. The arrays are of size 0,
// which is a dummy value, but will be bigger after the compiler has filled them
// in.
var (
firstInterfaceNum uint16 // the lowest typecode that has at least one method
methodSetRanges [0]methodSetRange // indexes into methodSetSignatures and methodSetFunctions
methodSetSignatures [0]uint16 // uniqued method ID
methodSetFunctions [0]*uint8 // function pointer of method
)
// Get the function pointer for the method on the interface.
// This is a compiler intrinsic.
func interfaceMethod(itf _interface, method uint16) *uint8 {
// This function doesn't do bounds checking as the supplied method must be
// in the list of signatures. The compiler will only emit
// runtime.interfaceMethod calls when the method actually exists on this
// interface (proven by the typechecker).
i := methodSetRanges[itf.typecode-firstInterfaceNum].index
for {
if methodSetSignatures[i] == method {
return methodSetFunctions[i]
}
i++
}
}