assign.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. package compiler
  2. import (
  3. "kumachan/lang/source"
  4. "kumachan/lang/typsys"
  5. "kumachan/interpreter/program"
  6. )
  7. func assign(expected typsys.Type, expr *program.Expr, ctx *exprContext, s0 *typsys.InferringState) (*program.Expr, *typsys.InferringState, *source.Error) {
  8. var loc = expr.Info.Location
  9. var t = expr.Type.Type
  10. if certain, ok := typsys.GetCertainOrInferred(expected, s0); ok {
  11. expected = certain.Type
  12. }
  13. // direct
  14. if ok, s1 := typsys.Match(expected, t, s0); ok {
  15. return expr, s1, nil
  16. }
  17. // convert to interface
  18. if I, Id, Ia, ok := getInterface(expected, ctx); ok {
  19. var d, a, ok = getTypeDefArgs(t, ctx)
  20. if !(ok) { goto NG }
  21. if _, is_interface := d.Content.(typsys.Interface); is_interface {
  22. // interface -> interface (upward)
  23. var ok, s1 = typsys.MatchAll(Ia, a, s0)
  24. if !(ok) { goto NG }
  25. { var It, ok = typsys.GetCertainOrInferred(expected, s1)
  26. if !(ok) { goto NG }
  27. { var up, ok = getInterfacePath(d, Id, ctx, nil)
  28. if !(ok) { goto NG }
  29. var converted = &program.Expr {
  30. Type: It,
  31. Info: expr.Info,
  32. Content: program.InterfaceTransformUpward {
  33. Arg: expr,
  34. Path: up,
  35. },
  36. }
  37. return converted, s1, nil }}
  38. } else {
  39. // concrete -> interface
  40. var table, ok = ctx.resolveDispatchTable(d, Id)
  41. if !(ok) {
  42. if isSamInterface(I, Id) {
  43. var field = I.FieldList[0]
  44. var field_t = inflateFieldType(field, Id, Ia)
  45. var ok, s1 = typsys.Match(field_t, t, s0)
  46. if !(ok) { goto NG }
  47. { var It, ok = typsys.GetCertainOrInferred(expected, s1)
  48. if !(ok) { goto NG }
  49. var converted = &program.Expr {
  50. Type: It,
  51. Info: expr.Info,
  52. Content: program.InterfaceFromSamValue {
  53. Value: expr,
  54. },
  55. }
  56. return converted, s1, nil }
  57. }
  58. goto NG
  59. }
  60. { var ok, s1 = typsys.MatchAll(Ia, a, s0)
  61. if !(ok) { goto NG }
  62. { var It, ok = typsys.GetCertainOrInferred(expected, s1)
  63. if !(ok) { goto NG }
  64. var converted = &program.Expr {
  65. Type: It,
  66. Info: expr.Info,
  67. Content: program.Interface {
  68. ConcreteValue: expr,
  69. DispatchTable: table,
  70. },
  71. }
  72. return converted, s1, nil }}
  73. }
  74. }
  75. if e, ok := program.T_Maybe_(expected); ok {
  76. if _, Id, Ia, ok := getInterface(e, ctx); ok {
  77. if d, a, ok := getTypeDefArgs(t, ctx); ok {
  78. if ((d != Id) && !(program.T_Null_(t))) {
  79. if _, is_interface := d.Content.(typsys.Interface); is_interface {
  80. // interface -> interface (downward)
  81. var ok, s1 = typsys.MatchAll(Ia, a, s0)
  82. if !(ok) { goto NG }
  83. { var maybe_It, ok = typsys.GetCertainOrInferred(expected, s1)
  84. if !(ok) { goto NG }
  85. { var down, ok = getInterfacePath(Id, d, ctx, nil)
  86. if !(ok) { goto NG }
  87. var converted = &program.Expr {
  88. Type: maybe_It,
  89. Info: expr.Info,
  90. Content: program.InterfaceTransformDownward {
  91. Arg: expr,
  92. Depth: len(down),
  93. Target: Id.Ref.String(),
  94. },
  95. }
  96. return converted, s1, nil }}
  97. } else {
  98. // interface -> concrete
  99. // *** implemented as lens2 interior reference ***
  100. goto NG
  101. }
  102. }}}}
  103. // convert to union
  104. if U, Ud, Ua, ok := getUnion(expected, ctx); ok {
  105. var converted *program.Expr
  106. var s2 *typsys.InferringState
  107. var key string
  108. var found = false
  109. for i, field := range U.FieldList {
  110. var index = i
  111. var field_t = inflateFieldType(field, Ud, Ua)
  112. if ok, s1 := typsys.Match(field_t, t, s0); ok {
  113. if certain, ok := typsys.GetCertainOrInferred(expected, s1); ok {
  114. if found {
  115. var this_key = field.Name
  116. return nil, nil, source.MakeError(loc,
  117. E_AmbiguousAssignmentToUnion {
  118. Union: Ud.Ref.String(),
  119. Key1: key,
  120. Key2: this_key,
  121. })
  122. }
  123. found = true
  124. key = field.Name
  125. s2 = s1
  126. converted = &program.Expr {
  127. Type: certain,
  128. Info: expr.Info,
  129. Content: program.Union {
  130. Index: index,
  131. Value: expr,
  132. },
  133. }
  134. }}
  135. }
  136. if found {
  137. return converted, s2, nil
  138. } else {
  139. goto NG
  140. }
  141. }
  142. // convert to Int
  143. if program.T_Int_(expected) {
  144. var _, _, ok = getEnum(t, ctx)
  145. if !(ok) { goto NG }
  146. var converted = &program.Expr {
  147. Type: typsys.CertainType { Type: program.T_Int() },
  148. Info: expr.Info,
  149. Content: program.EnumToInt { EnumValue: expr },
  150. }
  151. return converted, s0, nil
  152. }
  153. // convert to T_IntoReflectType(e)
  154. if e, ok := program.T_IntoReflectType_(expected); ok {
  155. { var ok = program.T_DummyReflectType_(expr.Type.Type)
  156. if !(ok) { goto NG }
  157. { var certain, ok = typsys.GetCertainOrInferred(e, s0)
  158. if !(ok) { goto NG }
  159. var rt = program.MakeReflectType_(certain)
  160. var converted_t = program.T_IntoReflectType(certain.Type)
  161. var converted = &program.Expr {
  162. Type: typsys.CertainType { Type: converted_t },
  163. Info: expr.Info,
  164. Content: program.ReflectType { Type: rt },
  165. }
  166. return converted, s0, nil }}
  167. }
  168. // convert to T_IntoReflectValue(e)
  169. if e, ok := program.T_IntoReflectValue_(expected); ok {
  170. var expr, s1, err = assign(e, expr, ctx, s0)
  171. if err != nil { return nil, nil, err }
  172. var rt = program.MakeReflectType_(expr.Type)
  173. var converted_t = program.T_IntoReflectValue(expr.Type.Type)
  174. var converted = &program.Expr {
  175. Type: typsys.CertainType { Type: converted_t },
  176. Info: expr.Info,
  177. Content: program.ReflectValue {
  178. Type: rt,
  179. Value: expr,
  180. },
  181. }
  182. return converted, s1, nil
  183. }
  184. NG:
  185. return nil, nil, source.MakeError(loc,
  186. E_NotAssignable {
  187. From: typsys.Describe(t),
  188. To: typsys.DescribeWithInferringState(expected, s0),
  189. })
  190. }