expr_misc.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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. func checkBlank(B ast.TermBlank) ExprChecker {
  10. return makeExprChecker(B.Location, func(cc *checkContext) checkResult {
  11. return cc.error(E_BlankTerm {})
  12. })
  13. }
  14. func checkCast(arg_node ast.Expr, target ast.VariousType, loc source.Location) ExprChecker {
  15. return makeExprChecker(loc, func(cc *checkContext) checkResult {
  16. var type_ctx = cc.typeConsContext()
  17. var target_t, err1 = newType(target, type_ctx)
  18. if err1 != nil { return cc.propagate(err1) }
  19. var arg, err2 = cc.checkChildExpr(target_t, arg_node)
  20. if err2 != nil { return cc.propagate(err2) }
  21. return cc.assign(target_t, checked.Wrapper { Inner: arg })
  22. })
  23. }
  24. func checkInterior(arg *checked.Expr, mod_name ast.ModuleName, item_name ast.Identifier, loc source.Location) ExprChecker {
  25. return makeExprChecker(loc, func(cc *checkContext) checkResult {
  26. var mod_name_not_empty = mod_name.NotEmpty
  27. { var i_def, i_args, op, base, is_interface = cc.unboxInteriorReferableInterfaceDef(arg)
  28. if !(is_interface) && mod_name_not_empty {
  29. return cc.propagate(source.MakeError(arg.Info.Location,
  30. E_DynamicCastFromNonInterface {
  31. Type: cc.describeType(arg.Type),
  32. }))
  33. }
  34. if is_interface {
  35. var c_name, err = NameFrom(
  36. mod_name, item_name, cc.exprContext.ModuleInfo,
  37. )
  38. if err != nil {
  39. return cc.propagate(err)
  40. }
  41. var ctx = cc.typeConsContext()
  42. var c_def_, c_def_desc, exists = ctx.ResolveTypeDefName(c_name)
  43. if !(exists) {
  44. return cc.propagate(source.MakeError(item_name.Location,
  45. E_TypeNotFound { Which: c_def_desc() }))
  46. }
  47. var c_def = c_def_.TypeDef
  48. var _, c_is_interface = c_def.Content.(*typsys.Interface)
  49. if c_is_interface {
  50. return cc.error(E_DynamicCastToInterface {})
  51. }
  52. var p = ImplPair {
  53. ConcreteType: c_def,
  54. InterfaceType: i_def,
  55. }
  56. var table, ok = cc.exprContext.DispatchMapping[p]
  57. if !(ok) {
  58. var c_type_name = name.TypeName { Name: c_name }
  59. var i_type_name = i_def.Name
  60. return cc.error(
  61. E_NotImplementation {
  62. Type: c_type_name.String(),
  63. Interface: i_type_name.String(),
  64. })
  65. }
  66. var c_type = &typsys.NestedType { Content: typsys.Ref {
  67. Def: c_def,
  68. Args: i_args,
  69. } }
  70. var ref_type = cc.getType(coreCaseRef(
  71. base,
  72. c_type,
  73. ))
  74. return cc.assign(
  75. ref_type,
  76. checked.InteriorRef {
  77. Base: arg,
  78. Table: table,
  79. Kind: checked.RK_InterfaceCase,
  80. Operand: op,
  81. })
  82. } }
  83. { var key = ast.Id2String(item_name)
  84. { var record, op, base, is_record = cc.unboxInteriorReferableRecord(arg)
  85. if is_record {
  86. var index, exists = record.FieldIndexMap[key]
  87. if !(exists) { goto key_not_found }
  88. var field_t = record.Fields[index].Type
  89. var ref_t = cc.getType(coreProjRef(base, field_t))
  90. return cc.assign(
  91. ref_t,
  92. checked.InteriorRef {
  93. Base: arg,
  94. Index: index,
  95. Kind: checked.RK_Proj,
  96. Operand: op,
  97. })
  98. } }
  99. { var enum, ea, op, base, is_enum = cc.unboxInteriorReferableEnum(arg)
  100. if is_enum {
  101. var ci uint
  102. var cd *typsys.TypeDef
  103. var found = false
  104. for i, case_def := range enum.CaseTypes {
  105. if case_def.Name.ItemName == key {
  106. ci = uint(i)
  107. cd = case_def
  108. found = true
  109. }
  110. }
  111. if !(found) { goto key_not_found }
  112. var case_t = &typsys.NestedType { Content:
  113. typsys.Ref {
  114. Def: cd,
  115. Args: ea,
  116. } }
  117. var ref_t = cc.getType(coreCaseRef(base, case_t))
  118. return cc.assign(
  119. ref_t,
  120. checked.InteriorRef {
  121. Base: arg,
  122. Index: ci,
  123. Kind: checked.RK_Case,
  124. Operand: op,
  125. })
  126. } }
  127. key_not_found:
  128. return cc.propagate(source.MakeError(item_name.Location,
  129. E_NoSuchFieldOrCase {
  130. FieldName: key,
  131. TypeName: cc.describeTypeOf(arg),
  132. })) }
  133. })
  134. }
  135. func checkList(L ast.Array) ExprChecker {
  136. return makeExprChecker(L.Location, func(cc *checkContext) checkResult {
  137. if len(L.Items) == 0 {
  138. return cc.assign(
  139. cc.getType(coreList(typsys.BottomType {})),
  140. checked.List {
  141. Items: [] *checked.Expr {},
  142. Info: checked.ListInfo {},
  143. })
  144. }
  145. var item_t, ok = cc.getExpectedListItemType(cc.expected)
  146. if ok {
  147. var items = make([] *checked.Expr, len(L.Items))
  148. for i, item_node := range L.Items {
  149. var item, err = cc.checkChildExpr(item_t, item_node)
  150. if err != nil { return cc.throw(err) }
  151. items[i] = item
  152. }
  153. var item_t, err = cc.requireCertainOrInferredType(item_t)
  154. if err != nil { return cc.throw(err) }
  155. var list_t = cc.getType(coreList(item_t))
  156. return cc.assign(
  157. list_t,
  158. checked.List {
  159. Items: items,
  160. Info: getListInfo(item_t),
  161. })
  162. } else {
  163. var item_t = typsys.Type(nil)
  164. var items = make([] *checked.Expr, len(L.Items))
  165. for i, item_node := range L.Items {
  166. var item, err = cc.checkChildExpr(item_t, item_node)
  167. if err != nil { return cc.propagate(err) }
  168. if item_t == nil {
  169. item_t = item.Type
  170. }
  171. items[i] = item
  172. }
  173. if item_t == nil { panic("something went wrong") }
  174. var list_t = cc.getType(coreList(item_t))
  175. return cc.assign(
  176. list_t,
  177. checked.List {
  178. Items: items,
  179. Info: getListInfo(item_t),
  180. })
  181. }
  182. })
  183. }
  184. func checkPipelineLambda(P ast.PipelineLambda) ExprChecker {
  185. return checkQuickLambda(P.Node, quickPipelineLambda(P))
  186. }
  187. func quickPipelineLambda(P ast.PipelineLambda) quickLambda {
  188. return func(arg ast.Expr) ast.Expr {
  189. return ast.Expr {
  190. Node: P.Node,
  191. Term: ast.WrapExprIntoTerm(arg),
  192. Pipeline: P.Pipeline,
  193. }
  194. }
  195. }
  196. func checkConstructorLambda(C ast.ConstructorLambda) ExprChecker {
  197. return makeExprChecker(C.Location, func(cc *checkContext) checkResult {
  198. var type_ctx = cc.typeConsContext()
  199. var f, err = quickConstructorLambda(C, type_ctx)
  200. if err != nil { return cc.propagate(err) }
  201. return cc.forward(checkQuickLambda(C.Node, f))
  202. })
  203. }
  204. func quickConstructorLambda(C ast.ConstructorLambda, type_ctx TypeConsContext) (quickLambda, *source.Error) {
  205. var def, args, err = newRefNoCheckArgQuantity(C.Type, type_ctx)
  206. if err != nil { return nil, err }
  207. return func(arg ast.Expr) ast.Expr {
  208. return ast.Expr {
  209. Node: C.Node,
  210. Term: ast.VariousTerm {
  211. Node: C.Node,
  212. Term: ConstructorCallTerm {
  213. TypeDef: def,
  214. TypeArgs: args,
  215. Argument: arg,
  216. },
  217. },
  218. }
  219. }, nil
  220. }