expr3.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. package compiler
  2. import (
  3. "kumachan/lang/source"
  4. "kumachan/lang/typsys"
  5. "kumachan/lang/textual/ast"
  6. "kumachan/interpreter/program"
  7. )
  8. func checkCast(cast ast.Cast, in ast.Expr, cc *exprCheckContext) (*program.Expr, *source.Error) {
  9. var loc = cast.Location
  10. var target, err = cc.context.makeType(cast.Target)
  11. if err != nil { return nil, err }
  12. { var expr, err = cc.checkChildExpr(target.Type, in)
  13. if err != nil { return nil, err }
  14. return cc.assign(target, loc,
  15. program.Wrapper { Inner: expr })
  16. }
  17. }
  18. func checkPipeGet(get ast.PipeGet, in ast.Expr, cc *exprCheckContext) (*program.Expr, *source.Error) {
  19. var key = ast.Id2String(get.Key)
  20. var loc = get.Location
  21. var ctx = cc.context
  22. var in_expr, err = cc.checkChildExpr(nil, in)
  23. if err != nil { return nil, err }
  24. var in_t = in_expr.Type
  25. if record, def, args, ok := getRecord(in_t.Type, ctx); ok {
  26. if field_index, ok := record.FieldIndexMap[key]; ok {
  27. var field = record.FieldList[field_index]
  28. var field_t_ = inflateFieldType(field, def, args)
  29. var field_t = typsys.CertainType { Type: field_t_ }
  30. return cc.assign(field_t, loc,
  31. program.FieldValue {
  32. Record: in_expr,
  33. Index: field_index,
  34. })
  35. }}
  36. if inner_t_, ok := program.T_Observable_(in_t.Type); ok {
  37. if record, def, args, ok := getRecord(inner_t_, ctx); ok {
  38. if field_index, ok := record.FieldIndexMap[key]; ok {
  39. var field = record.FieldList[field_index]
  40. var field_t_ = inflateFieldType(field, def, args)
  41. var field_ob_t_ = program.T_Observable(field_t_)
  42. var field_ob_t = typsys.CertainType { Type: field_ob_t_ }
  43. return cc.assign(field_ob_t, loc,
  44. program.ObservableFieldProjection {
  45. Base: in_expr,
  46. Index: field_index,
  47. })
  48. }}}
  49. if method_t, f, index, path, ok := ctx.resolveMethod(in_t, key, nil); ok {
  50. if f != nil {
  51. return cc.assign(method_t, loc,
  52. program.ConcreteMethodValue {
  53. Location: loc,
  54. This: in_expr,
  55. Path: path,
  56. Method: f,
  57. })
  58. } else {
  59. return cc.assign(method_t, loc,
  60. program.AbstractMethodValue {
  61. Location: loc,
  62. Interface: in_expr,
  63. Path: path,
  64. Index: index,
  65. })
  66. }
  67. }
  68. return cc.error(loc,
  69. E_NoSuchFieldOrMethod {
  70. FieldName: key,
  71. TypeDesc: typsys.DescribeCertain(in_t),
  72. })
  73. }
  74. func checkPipeInterior(interior ast.PipeInterior, in ast.Expr, cc *exprCheckContext) (*program.Expr, *source.Error) {
  75. var ref = getRef(interior.RefBase)
  76. var loc = interior.Location
  77. var ctx = cc.context
  78. var in_expr, err = cc.checkChildExpr(nil, in)
  79. if err != nil { return nil, err }
  80. var in_t = in_expr.Type
  81. if ref.Namespace == "" {
  82. var key = ref.ItemName
  83. if r, d, a, o, b, ok := getInteriorReferableRecord(in_t, ctx); ok {
  84. var index, exists = r.FieldIndexMap[key]
  85. if !(exists) { goto NG }
  86. var field = r.FieldList[index]
  87. var field_t_ = inflateFieldType(field, d, a)
  88. var lens1_t_ = program.T_Lens1(b.Type, field_t_)
  89. var lens1_t = typsys.CertainType { Type: lens1_t_}
  90. return cc.assign(lens1_t, loc,
  91. program.InteriorRef {
  92. Base: in_expr,
  93. Index: index,
  94. Kind: program.RK_RecordField,
  95. Operand: o,
  96. })
  97. }
  98. if e, o, b, ok := getInteriorReferableEnum(in_t, ctx); ok {
  99. var index, exists = e.FieldIndexMap[key]
  100. if !(exists) { goto NG }
  101. var null_t = program.T_Null()
  102. var lens2_t_ = program.T_Lens2(b.Type, null_t)
  103. var lens2_t = typsys.CertainType { Type: lens2_t_ }
  104. return cc.assign(lens2_t, loc,
  105. program.InteriorRef {
  106. Base: in_expr,
  107. Index: index,
  108. Kind: program.RK_EnumItem,
  109. Operand: o,
  110. })
  111. }
  112. if u, d, a, o, b, ok := getInteriorReferableUnion(in_t, ctx); ok {
  113. var index, exists = u.FieldIndexMap[key]
  114. if !(exists) { goto NG }
  115. var field = u.FieldList[index]
  116. var field_t_ = inflateFieldType(field, d, a)
  117. var lens2_t_ = program.T_Lens2(b.Type, field_t_)
  118. var lens2_t = typsys.CertainType { Type: lens2_t_ }
  119. return cc.assign(lens2_t, loc,
  120. program.InteriorRef {
  121. Base: in_expr,
  122. Index: index,
  123. Kind: program.RK_UnionItem,
  124. Operand: o,
  125. })
  126. }
  127. }
  128. if _, I, a, o, b, ok := getInteriorReferableInterface(in_t, ctx); ok {
  129. var C, exists = ctx.resolveType(ref)
  130. if !(exists) { goto NG }
  131. var _, is_interface = C.Content.(typsys.Interface)
  132. if is_interface { goto NG }
  133. var table, ok = ctx.resolveDispatchTable(C, I)
  134. if !(ok) { goto NG }
  135. var base_type = b.Type
  136. var concrete_type = typsys.RefType { Def: C.Ref, Args: a }
  137. var lens2_t_ = program.T_Lens2(base_type, concrete_type)
  138. var lens2_t = typsys.CertainType { Type: lens2_t_ }
  139. return cc.assign(lens2_t, loc,
  140. program.InteriorRef {
  141. Base: in_expr,
  142. Table: table,
  143. Kind: program.RK_DynamicCast,
  144. Operand: o,
  145. })
  146. }
  147. NG:
  148. return cc.error(loc,
  149. E_InteriorRefUnavailable {
  150. InteriorRef: ref.String(),
  151. TypeDesc: typsys.DescribeCertain(in_t),
  152. })
  153. }
  154. func checkPipeInfix(infix ast.PipeInfix, in ast.Expr, cc *exprCheckContext) (*program.Expr, *source.Error) {
  155. if infix.Off {
  156. return cc.forwardTo(in)
  157. }
  158. var left, err = cc.checkChildExpr(nil, in)
  159. if err != nil { return nil, err }
  160. var right = infix.PipeCall
  161. var op = infix.Callee
  162. var loc = infix.Location
  163. return checkCallFunRef(op, left, right, true, loc, cc)
  164. }
  165. func checkInfixTerm(I ast.InfixTerm, cc *exprCheckContext) (*program.Expr, *source.Error) {
  166. var left, err = cc.checkChildExpr(nil, I.Left)
  167. if err != nil { return nil, err }
  168. var right = craftInfixRight(I.Right, I.Node)
  169. var op = I.Operator
  170. var loc = I.Location
  171. return checkCallFunRef(op, left, right, true, loc, cc)
  172. }
  173. func checkPipeCall(args ast.VariousPipeCall, callee ast.Expr, cc *exprCheckContext) (*program.Expr, *source.Error) {
  174. var loc = callee.Location
  175. if ref_node, tag, is_new, is_ref := ast.GetStandaloneRef(callee); is_ref {
  176. if is_new {
  177. return checkNewRecord(ref_node, args, tag, loc, cc)
  178. } else {
  179. var ctx = cc.context
  180. var ref = getRef(ref_node.Base)
  181. if ((ref.Namespace == "") && ctx.hasBinding(ref.ItemName)) {
  182. return checkCallExpr(callee, args, cc)
  183. } else {
  184. return checkCallFunRef(ref_node, nil, args, false, loc, cc)
  185. }
  186. }
  187. } else {
  188. return checkCallExpr(callee, args, cc)
  189. }
  190. }