interface.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. package checker
  2. import (
  3. "kumachan/interpreter/lang/ast"
  4. "kumachan/interpreter/lang/common/name"
  5. "kumachan/interpreter/lang/common/source"
  6. "kumachan/interpreter/compiler/checker/typsys"
  7. "kumachan/interpreter/compiler/checker/checked"
  8. )
  9. type DispatchMapping (map[ImplPair] *checked.DispatchTable)
  10. type ImplPair struct {
  11. ConcreteType *typsys.TypeDef
  12. InterfaceType *typsys.TypeDef
  13. }
  14. func generateDispatchMapping (
  15. types typeList,
  16. functions FunctionRegistry,
  17. ) (DispatchMapping, source.Errors) {
  18. var mapping = make(DispatchMapping)
  19. var errs source.Errors
  20. for _, def := range types {
  21. var _, is_interface = def.Content.(*typsys.Interface)
  22. if is_interface {
  23. continue
  24. }
  25. var con = def.TypeDef
  26. var err = (func() *source.Error {
  27. for _, impl := range con.Implements {
  28. var _, err = makeDispatchTable(functions, con, impl, mapping)
  29. if err != nil { return err }
  30. }
  31. return nil
  32. })()
  33. source.ErrorsJoin(&errs, err)
  34. }
  35. if errs != nil { return nil, errs }
  36. return mapping, nil
  37. }
  38. func makeDispatchTable (
  39. f_reg FunctionRegistry,
  40. con *typsys.TypeDef,
  41. impl *typsys.TypeDef,
  42. mapping DispatchMapping,
  43. ) (*checked.DispatchTable, *source.Error) {
  44. var _, con_invalid = con.Content.(*typsys.Interface)
  45. if con_invalid {
  46. panic("invalid argument")
  47. }
  48. var pair = ImplPair {
  49. ConcreteType: con,
  50. InterfaceType: impl,
  51. }
  52. var existing, exists = mapping[pair]
  53. if exists {
  54. // diamond situation
  55. return existing, nil
  56. }
  57. var con_t = defType(con)
  58. var fields = impl.Content.(*typsys.Interface).Methods.Fields
  59. var methods = make([] checked.Method, len(fields))
  60. for i, field := range fields {
  61. var method_name = field.Name
  62. var method_t = methodType(con, impl, field.Type)
  63. var method_full_name = name.Name {
  64. ModuleName: con.Name.ModuleName,
  65. ItemName: field.Name,
  66. }
  67. var detail = func() ImplError { return ImplError {
  68. Concrete: con.Name.String(),
  69. Interface: impl.Name.String(),
  70. Method: method_name,
  71. } }
  72. var m_group, func_exists = f_reg[method_full_name]
  73. var m_index, field_exists = (func() (*uint, bool) {
  74. var record, is_record = getBoxedRecord(con)
  75. if is_record {
  76. var index, exists = record.FieldIndexMap[method_name]
  77. return &index, exists
  78. } else {
  79. return nil, false
  80. }
  81. })()
  82. if func_exists && field_exists {
  83. return nil, source.MakeError(con.Location,
  84. E_ImplMethodAmbiguous {
  85. ImplError: detail(),
  86. })
  87. } else if !(func_exists) && field_exists {
  88. methods[i] = checked.MethodField { Index: *(m_index) }
  89. } else if func_exists && !(field_exists) {
  90. var method_f *Function = nil
  91. var found = false
  92. for _, f := range m_group {
  93. if f.AstNode.Kind != ast.FK_Method {
  94. continue
  95. }
  96. var implicit = f.Signature.ImplicitContext
  97. var params = f.Signature.TypeParameters
  98. var io = f.Signature.InputOutput
  99. if len(implicit.Fields) > 0 {
  100. panic("something went wrong")
  101. }
  102. var in = typsys.TypeOpParameterReplace (
  103. params, con.Parameters, io.Input,
  104. )
  105. var out = typsys.TypeOpParameterReplace (
  106. params, con.Parameters, io.Output,
  107. )
  108. var ok = typsys.TypeOpEqualTypeVec (
  109. [] typsys.Type { in, out },
  110. [] typsys.Type { con_t, method_t },
  111. )
  112. if ok {
  113. if found {
  114. return nil, source.MakeError(con.Location,
  115. E_ImplMethodDuplicateCompatible {
  116. ImplError: detail(),
  117. })
  118. }
  119. found = true
  120. method_f = f
  121. }
  122. }
  123. if !(found) {
  124. return nil, source.MakeError(con.Location,
  125. E_ImplMethodNoneCompatible {
  126. ImplError: detail(),
  127. })
  128. }
  129. methods[i] = checked.MethodFunction { Name: method_f.Name }
  130. } else {
  131. return nil, source.MakeError(con.Location,
  132. E_ImplMethodNoSuchFunctionOrField {
  133. ImplError: detail(),
  134. })
  135. }
  136. }
  137. var included = make([] *checked.DispatchTable, len(impl.Implements))
  138. for i, impl_impl := range impl.Implements {
  139. var table, err = makeDispatchTable(f_reg, con, impl_impl, mapping)
  140. if err != nil { return nil, err }
  141. included[i] = table
  142. }
  143. var table = &checked.DispatchTable {
  144. Methods: methods,
  145. Included: included,
  146. Concrete: con.Name,
  147. Interface: impl.Name,
  148. }
  149. mapping[pair] = table
  150. return table, nil
  151. }
  152. func getBoxedRecord(def *typsys.TypeDef) (typsys.Record, bool) {
  153. var box, is_box = def.Content.(*typsys.Box)
  154. if is_box {
  155. var record, is_record = getRecord(box.InnerType)
  156. return record, is_record
  157. } else {
  158. return typsys.Record {}, false
  159. }
  160. }
  161. func defType(def *typsys.TypeDef) typsys.Type {
  162. return &typsys.NestedType {
  163. Content: typsys.Ref {
  164. Def: def,
  165. Args: (func() ([] typsys.Type) {
  166. var args = make([] typsys.Type, len(def.Parameters))
  167. for i := range def.Parameters {
  168. var p = &(def.Parameters[i])
  169. args[i] = typsys.ParameterType { Parameter: p }
  170. }
  171. return args
  172. })(),
  173. },
  174. }
  175. }
  176. func methodType(con *typsys.TypeDef, impl *typsys.TypeDef, raw typsys.Type) typsys.Type {
  177. if len(con.Parameters) != len(impl.Parameters) {
  178. panic("something went wrong")
  179. }
  180. return typsys.TypeOpMap(raw, func(t typsys.Type) (typsys.Type, bool) {
  181. var p, is_parameter = t.(typsys.ParameterType)
  182. if is_parameter {
  183. for i := range impl.Parameters {
  184. var impl_p = &(impl.Parameters[i])
  185. if p.Parameter == impl_p {
  186. var con_p = &(con.Parameters[i])
  187. return typsys.ParameterType { Parameter: con_p }, true
  188. }
  189. }
  190. return nil, false
  191. } else {
  192. return nil, false
  193. }
  194. })
  195. }
  196. func getInterface(t typsys.Type) (*typsys.Interface, *typsys.TypeDef, ([] typsys.Type), bool) {
  197. var nested, is_nested = t.(*typsys.NestedType)
  198. if !(is_nested) { return nil, nil, nil, false }
  199. var ref, is_ref = nested.Content.(typsys.Ref)
  200. if !(is_ref) { return nil, nil, nil, false }
  201. var interface_, is_interface = ref.Def.Content.(*typsys.Interface)
  202. if !(is_interface) { return nil, nil, nil, false }
  203. return interface_, ref.Def, ref.Args, true
  204. }
  205. func unboxInterface(t typsys.Type, mod string) (*typsys.Interface, *typsys.TypeDef, ([] typsys.Type), bool) {
  206. var interface_, def, args, is_interface = getInterface(t)
  207. if is_interface {
  208. return interface_, def, args, true
  209. } else {
  210. var inner, _, exists = typsys.Unbox(t, mod)
  211. if exists {
  212. return unboxInterface(inner, mod)
  213. } else {
  214. return nil, nil, nil, false
  215. }
  216. }
  217. }