typutil.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. package compiler
  2. import (
  3. "kumachan/lang/typsys"
  4. "kumachan/interpreter/program"
  5. )
  6. func getTypeDefArgs(t typsys.Type, ctx *exprContext) (*typsys.TypeDef, ([] typsys.Type), bool) {
  7. if ref_type, ok := t.(typsys.RefType); ok {
  8. var def, exists = ctx.context.lookupType(ref_type.Def)
  9. if !(exists) { panic("something went wrong") }
  10. var args = ref_type.Args
  11. return def, args, true
  12. } else {
  13. return nil, nil, false
  14. }
  15. }
  16. func inflateFieldType(field typsys.Field, def *typsys.TypeDef, args ([] typsys.Type)) typsys.Type {
  17. var raw_type = field.Type
  18. var params = def.Parameters
  19. var inflated_type = typsys.Inflate(raw_type, params, args)
  20. return inflated_type
  21. }
  22. func haveIdenticalTypeParams(a *typsys.TypeDef, b *typsys.TypeDef) bool {
  23. if len(a.Parameters) != len(b.Parameters) {
  24. return false
  25. }
  26. var n = len(a.Parameters)
  27. for i := 0; i < n; i += 1 {
  28. if a.Parameters[i] != b.Parameters[i] {
  29. return false
  30. }
  31. }
  32. return true
  33. }
  34. func getRecord(t typsys.Type, ctx *exprContext) (typsys.Record, *typsys.TypeDef, ([] typsys.Type), bool) {
  35. { var def, args, ok = getTypeDefArgs(t, ctx)
  36. if !(ok) { goto NG }
  37. { var record, ok = def.Content.(typsys.Record)
  38. if !(ok) { goto NG }
  39. return record, def, args, true } }
  40. NG:
  41. return typsys.Record {}, nil, nil, false
  42. }
  43. func getUnion(t typsys.Type, ctx *exprContext) (typsys.Union, *typsys.TypeDef, ([] typsys.Type), bool) {
  44. var def, args, ok = getTypeDefArgs(t, ctx)
  45. if !(ok) { goto NG }
  46. { var union, ok = def.Content.(typsys.Union)
  47. if !(ok) { goto NG }
  48. return union, def, args, true }
  49. NG:
  50. return typsys.Union {}, nil, nil, false
  51. }
  52. func getEnum(t typsys.Type, ctx *exprContext) (typsys.Enum, *typsys.TypeDef, bool) {
  53. var def, _, ok = getTypeDefArgs(t, ctx)
  54. if !(ok) { goto NG }
  55. { var enum, ok = def.Content.(typsys.Enum)
  56. if !(ok) { goto NG }
  57. return enum, def, true }
  58. NG:
  59. return typsys.Enum {}, nil, false
  60. }
  61. func getInterface(t typsys.Type, ctx *exprContext) (typsys.Interface, *typsys.TypeDef, ([] typsys.Type), bool) {
  62. var def, args, ok = getTypeDefArgs(t, ctx)
  63. if !(ok) { goto NG }
  64. { var interface_, ok = def.Content.(typsys.Interface)
  65. if !(ok) { goto NG }
  66. return interface_, def, args, true }
  67. NG:
  68. return typsys.Interface {}, nil, nil, false
  69. }
  70. func isSamInterface(I typsys.Interface, Id *typsys.TypeDef) bool {
  71. return (len(Id.Interfaces) == 0) && (len(I.FieldList) == 1)
  72. }
  73. func getSamInterfaceMethodType(t typsys.Type, ctx *exprContext) (typsys.Type, bool) {
  74. // note: behavior of this function should be in sync with assign()
  75. var I, Id, Ia, is_interface = getInterface(t, ctx)
  76. if is_interface {
  77. if isSamInterface(I, Id) {
  78. var field = I.FieldList[0]
  79. var field_type = inflateFieldType(field, Id, Ia)
  80. return field_type, true
  81. }
  82. }
  83. return nil, false
  84. }
  85. func getInterfacePath(root *typsys.TypeDef, descendant *typsys.TypeDef, ctx *exprContext, base ([] int)) ([] int, bool) {
  86. for i, child_ref := range root.Interfaces {
  87. var child, exists = ctx.context.lookupType(child_ref)
  88. if !(exists) { panic("something went wrong") }
  89. var current = append(base, i)
  90. if child == descendant {
  91. return current, true
  92. } else {
  93. var path, ok = getInterfacePath(child, descendant, ctx, current)
  94. if ok {
  95. return path, true
  96. }
  97. }
  98. }
  99. return nil, false
  100. }
  101. func getInteriorReferableRecord(base_t typsys.CertainType, ctx *exprContext) (typsys.Record, *typsys.TypeDef, ([] typsys.Type), program.InteriorRefOperand, typsys.CertainType, bool) {
  102. if record, def, args, ok := getRecord(base_t.Type, ctx); ok {
  103. return record, def, args, program.RO_Direct, base_t, true
  104. }
  105. if base_t_, field_t, ok := program.T_Lens1_(base_t.Type); ok {
  106. var base_t = typsys.CertainType { Type: base_t_ }
  107. if record, def, args, ok := getRecord(field_t, ctx); ok {
  108. return record, def, args, program.RO_Lens1, base_t, true
  109. }
  110. }
  111. return typsys.Record{}, nil, nil, -1, typsys.CertainType{}, false
  112. }
  113. func getInteriorReferableEnum(base_t typsys.CertainType, ctx *exprContext) (typsys.Enum, program.InteriorRefOperand, typsys.CertainType, bool) {
  114. if enum, _, ok := getEnum(base_t.Type, ctx); ok {
  115. return enum, program.RO_Direct, base_t, true
  116. }
  117. if base_t_, field_t, ok := program.T_Lens1_(base_t.Type); ok {
  118. var base_t = typsys.CertainType { Type: base_t_ }
  119. if enum, _, ok := getEnum(field_t, ctx); ok {
  120. return enum, program.RO_Lens1, base_t, true
  121. }
  122. }
  123. if base_t_, field_t, ok := program.T_Lens2_(base_t.Type); ok {
  124. var base_t = typsys.CertainType { Type: base_t_ }
  125. if enum, _, ok := getEnum(field_t, ctx); ok {
  126. return enum, program.RO_Lens2, base_t, true
  127. }
  128. }
  129. return typsys.Enum{}, -1, typsys.CertainType{}, false
  130. }
  131. func getInteriorReferableUnion(base_t typsys.CertainType, ctx *exprContext) (typsys.Union, *typsys.TypeDef, ([] typsys.Type), program.InteriorRefOperand, typsys.CertainType, bool) {
  132. if union, def, args, ok := getUnion(base_t.Type, ctx); ok {
  133. return union, def, args, program.RO_Direct, base_t, true
  134. }
  135. if base_t_, field_t, ok := program.T_Lens1_(base_t.Type); ok {
  136. var base_t = typsys.CertainType { Type: base_t_ }
  137. if union, def, args, ok := getUnion(field_t, ctx); ok {
  138. return union, def, args, program.RO_Lens1, base_t, true
  139. }
  140. }
  141. if base_t_, field_t, ok := program.T_Lens2_(base_t.Type); ok {
  142. var base_t = typsys.CertainType { Type: base_t_ }
  143. if union, def, args, ok := getUnion(field_t, ctx); ok {
  144. return union, def, args, program.RO_Lens2, base_t, true
  145. }
  146. }
  147. return typsys.Union{}, nil, nil, -1, typsys.CertainType{}, false
  148. }
  149. func getInteriorReferableInterface(base_t typsys.CertainType, ctx *exprContext) (typsys.Interface, *typsys.TypeDef, ([] typsys.Type), program.InteriorRefOperand, typsys.CertainType, bool) {
  150. if interface_, def, args, ok := getInterface(base_t.Type, ctx); ok {
  151. return interface_, def, args, program.RO_Direct, base_t, true
  152. }
  153. if base_t_, field_t, ok := program.T_Lens1_(base_t.Type); ok {
  154. var base_t = typsys.CertainType { Type: base_t_ }
  155. if interface_, def, args, ok := getInterface(field_t, ctx); ok {
  156. return interface_, def, args, program.RO_Lens1, base_t, true
  157. }
  158. }
  159. if base_t_, field_t, ok := program.T_Lens2_(base_t.Type); ok {
  160. var base_t = typsys.CertainType { Type: base_t_ }
  161. if interface_, def, args, ok := getInterface(field_t, ctx); ok {
  162. return interface_, def, args, program.RO_Lens2, base_t, true
  163. }
  164. }
  165. return typsys.Interface{}, nil, nil, -1, typsys.CertainType{}, false
  166. }