signature.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. package muesli
  2. import "fmt"
  3. /*
  4. ParametersPerSignature is the amount of parameters that will be
  5. checked when type checking a signature. Limited mosty to allow hashability,
  6. that is, Signature is a map key.
  7. */
  8. const ParametersPerSignature = 32
  9. /*
  10. ReturnsPerSignature is the amount of parameters that will be
  11. checked when type checking a signature. Limited mosty to allow hashability,
  12. that is, Signature is a map key.
  13. */
  14. const ReturnsPerSignature = 8
  15. /* NamedWithType describes something that is named and that has a type. */
  16. type NamedWithType struct {
  17. Name WordValue
  18. Type TypeValue
  19. }
  20. /* Parameter describes the name and type of a parameter of a command. */
  21. type Parameter NamedWithType
  22. /* Returned describes the name and type of a value returned by a command.
  23. * It is in essence the same as a Parameter, the type is redefined to
  24. * avoid confounding the two.
  25. */
  26. type Returned NamedWithType
  27. /* Signature describes the types of the arguments that a callable takes,
  28. as well as the returned values.*/
  29. type Signature struct {
  30. Parameters [ParametersPerSignature]Parameter
  31. Returns [ReturnsPerSignature]Returned
  32. }
  33. func (s Signature) String() string {
  34. res := "["
  35. sep := ""
  36. for _, param := range s.Parameters {
  37. typ := param.Type
  38. if typ != ZeroType {
  39. res = res + sep + typ.String()
  40. sep = ", "
  41. }
  42. }
  43. res = res + "] -> ["
  44. sep = ""
  45. for _, param := range s.Returns {
  46. typ := param.Type
  47. if typ != ZeroType {
  48. res = res + sep + typ.String()
  49. sep = ", "
  50. }
  51. }
  52. res = res + "]"
  53. return res
  54. }
  55. func (s Signature) StringWithNames() string {
  56. res := "["
  57. sep := ""
  58. for _, param := range s.Parameters {
  59. typ := param.Type
  60. if typ != ZeroType {
  61. res = res + sep + string(param.Name) + " " + typ.String()
  62. sep = ", "
  63. }
  64. }
  65. res = res + "] -> ["
  66. sep = ""
  67. for _, param := range s.Returns {
  68. typ := param.Type
  69. if typ != ZeroType {
  70. res = res + sep + string(param.Name) + " " + typ.String()
  71. sep = ", "
  72. }
  73. }
  74. res = res + "]"
  75. return res
  76. }
  77. func (signature * Signature) SetReturns(types ... TypeValue) {
  78. for i := 0 ; i < len(types) && i < len(signature.Returns) ; i ++ {
  79. signature.Returns[i].Type = types[i]
  80. signature.Returns[i].Name = WordValue(fmt.Sprintf("res%d", i))
  81. }
  82. }
  83. func (signature * Signature) SetParameters(types ... TypeValue) {
  84. for i := 0 ; i < len(types) && i < len(signature.Parameters) ; i ++ {
  85. signature.Parameters[i].Type = types[i]
  86. signature.Parameters[i].Name = WordValue(fmt.Sprintf("arg%d", i))
  87. }
  88. }
  89. func NewSignature(types ... TypeValue) Signature {
  90. signature := Signature{}
  91. signature.SetParameters(types...)
  92. return signature
  93. }
  94. func NewSignatureWithNames(param ...Value) (Signature, error) {
  95. sign := Signature{}
  96. for i, j := 1, 0 ; i < len(param) ; i += 2 {
  97. name := param[i-1]
  98. typ := param[i]
  99. var ok bool
  100. var nv WordValue
  101. var tv TypeValue
  102. if nv, ok = name.(WordValue); !ok {
  103. return sign, fmt.Errorf("Not a word value: %v", name)
  104. }
  105. if tv, ok = typ.(TypeValue); !ok {
  106. return sign, fmt.Errorf("Not a type value: %v", typ)
  107. }
  108. sign.Parameters[j].Type = tv
  109. sign.Parameters[j].Name = nv
  110. j++
  111. }
  112. return sign, nil
  113. }
  114. // NoSignature is the default signature which means the VM will not do
  115. // any argument type checking when the callable is called.
  116. func NoSignature() Signature {
  117. return Signature{}
  118. }
  119. func CalculateSignature(arguments ...Value) Signature {
  120. signature := Signature{}
  121. for i := 0; i < len(signature.Parameters); i++ {
  122. if i < len(arguments) {
  123. signature.Parameters[i].Type = arguments[i].Type()
  124. } else {
  125. signature.Parameters[i].Type = AnyType
  126. }
  127. }
  128. return signature
  129. }
  130. func (tv TypeValue) IsMatch(other TypeValue) bool {
  131. if tv == AnyType || other == AnyType {
  132. return true
  133. }
  134. if tv == ZeroType || other == ZeroType {
  135. return true
  136. }
  137. return tv == other
  138. }
  139. func (signature Signature) IsMatch(other Signature) bool {
  140. for i, param := range signature.Parameters {
  141. t1 := param.Type
  142. t2 := other.Parameters[i].Type
  143. if !t1.IsMatch(t2) {
  144. return false
  145. }
  146. }
  147. return true
  148. }