sum.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. package checker
  2. import (
  3. "kumachan/loader"
  4. "kumachan/transformer/node"
  5. )
  6. func (impl Sum) ExprVal() {}
  7. type Sum struct {
  8. Value Expr
  9. Index uint
  10. }
  11. func (impl UnitValue) ExprVal() {}
  12. type UnitValue struct {}
  13. func (impl SemiTypedMatch) SemiExprVal() {}
  14. type SemiTypedMatch struct {
  15. Argument Expr
  16. Branches [] SemiTypedBranch
  17. }
  18. type SemiTypedBranch struct {
  19. IsDefault bool
  20. Index uint
  21. Pattern MaybePattern
  22. Value SemiExpr
  23. }
  24. func (impl Match) ExprVal() {}
  25. type Match struct {
  26. Argument Expr
  27. Branches [] Branch
  28. }
  29. type Branch struct {
  30. IsDefault bool
  31. Index uint
  32. Pattern MaybePattern
  33. Value Expr
  34. }
  35. func CheckSwitch(sw node.Switch, ctx ExprContext) (SemiExpr, *ExprError) {
  36. var info = ctx.GetExprInfo(sw.Node)
  37. var arg_semi, err = CheckTerm(sw.Argument, ctx)
  38. if err != nil { return SemiExpr{}, err }
  39. var arg_typed, ok = arg_semi.Value.(TypedExpr)
  40. if !ok { return SemiExpr{}, &ExprError {
  41. Point: ctx.GetErrorPoint(sw.Argument.Node),
  42. Concrete: E_ExplicitTypeRequired {},
  43. } }
  44. var arg_type = arg_typed.Type
  45. var union, union_args, is_union = ExtractUnion(arg_type, ctx)
  46. if !is_union { return SemiExpr{}, &ExprError {
  47. Point: arg_typed.Info.ErrorPoint,
  48. Concrete: E_InvalidMatchArgType {
  49. ArgType: ctx.DescribeType(arg_typed.Type),
  50. },
  51. } }
  52. var checked = make(map[loader.Symbol] bool)
  53. var has_default = false
  54. var branches = make([]SemiTypedBranch, len(sw.Branches))
  55. for i, branch := range sw.Branches {
  56. switch t := branch.Type.(type) {
  57. case node.Ref:
  58. if len(t.TypeArgs) > 0 {
  59. return SemiExpr{}, &ExprError {
  60. Point: ctx.GetErrorPoint(t.Node),
  61. Concrete: E_TypeParametersUnnecessary {},
  62. }
  63. }
  64. var maybe_type_sym = ctx.ModuleInfo.Module.SymbolFromRef(t)
  65. var type_sym, ok = maybe_type_sym.(loader.Symbol)
  66. if !ok { return SemiExpr{}, &ExprError {
  67. Point: ctx.GetErrorPoint(t.Module.Node),
  68. Concrete: E_TypeErrorInExpr { &TypeError {
  69. Point: ctx.GetErrorPoint(t.Module.Node),
  70. Concrete: E_ModuleOfTypeRefNotFound {
  71. Name: loader.Id2String(t.Module),
  72. },
  73. } },
  74. }}
  75. var g, exists = ctx.ModuleInfo.Types[type_sym]
  76. if !exists { return SemiExpr{}, &ExprError {
  77. Point: ctx.GetErrorPoint(t.Node),
  78. Concrete: E_TypeErrorInExpr { &TypeError {
  79. Point: ctx.GetErrorPoint(t.Node),
  80. Concrete: E_TypeNotFound {
  81. Name: type_sym,
  82. },
  83. } },
  84. } }
  85. var index, is_subtype = GetSubtypeIndex(union, type_sym)
  86. if !is_subtype { return SemiExpr{}, &ExprError{
  87. Point: ctx.GetErrorPoint(t.Node),
  88. Concrete: E_NotBranchType {
  89. Union: ctx.DescribeType(arg_type),
  90. TypeName: type_sym.String(),
  91. },
  92. } }
  93. if len(g.Params) != len(union_args) {
  94. panic("something went wrong")
  95. }
  96. var subtype = NamedType {
  97. Name: type_sym,
  98. Args: union_args,
  99. }
  100. var maybe_pattern MaybePattern
  101. var branch_ctx ExprContext
  102. switch pattern_node := branch.Pattern.(type) {
  103. case node.VariousPattern:
  104. var pattern, err = PatternFrom(pattern_node, subtype, ctx)
  105. if err != nil { return SemiExpr{}, err }
  106. maybe_pattern = pattern
  107. branch_ctx = ctx.WithShadowingPatternMatching(pattern)
  108. default:
  109. maybe_pattern = nil
  110. branch_ctx = ctx
  111. }
  112. var semi, err = Check(
  113. branch.Expr, branch_ctx,
  114. )
  115. if err != nil { return SemiExpr{}, err }
  116. branches[i] = SemiTypedBranch {
  117. IsDefault: false,
  118. Index: index,
  119. Pattern: maybe_pattern,
  120. Value: semi,
  121. }
  122. checked[type_sym] = true
  123. default:
  124. if has_default {
  125. return SemiExpr{}, &ExprError {
  126. Point: ctx.GetErrorPoint(branch.Node),
  127. Concrete: E_DuplicateDefaultBranch {},
  128. }
  129. }
  130. switch branch.Pattern.(type) {
  131. case node.VariousPattern:
  132. panic("something went wrong")
  133. }
  134. var semi, err = Check(branch.Expr, ctx)
  135. if err != nil { return SemiExpr{}, nil }
  136. branches[i] = SemiTypedBranch {
  137. IsDefault: true,
  138. Index: BadIndex,
  139. Pattern: Pattern {},
  140. Value: semi,
  141. }
  142. has_default = true
  143. }
  144. }
  145. if !has_default && len(checked) != len(union.SubTypes) {
  146. var missing = make([]string, 0)
  147. for _, subtype := range union.SubTypes {
  148. if !checked[subtype] {
  149. missing = append(missing, subtype.String())
  150. }
  151. }
  152. return SemiExpr{}, &ExprError {
  153. Point: ctx.GetErrorPoint(sw.Node),
  154. Concrete: E_IncompleteMatch { missing },
  155. }
  156. } else {
  157. return SemiExpr {
  158. Value: SemiTypedMatch {
  159. Argument: Expr(arg_typed),
  160. Branches: branches,
  161. },
  162. Info: info,
  163. }, nil
  164. }
  165. }
  166. func CheckIf(raw node.If, ctx ExprContext) (SemiExpr, *ExprError) {
  167. var if_node = DesugarElseIf(raw)
  168. var info = ctx.GetExprInfo(if_node.Node)
  169. var cond_semi, err = CheckTerm(if_node.Condition, ctx)
  170. if err != nil { return SemiExpr{}, err }
  171. var cond_typed, ok = cond_semi.Value.(TypedExpr)
  172. if !ok { return SemiExpr{}, &ExprError{
  173. Point: ctx.GetErrorPoint(if_node.Condition.Node),
  174. Concrete: E_NonBooleanCondition { Typed:false },
  175. } }
  176. switch T := cond_typed.Type.(type) {
  177. case NamedType:
  178. if T.Name == __Bool {
  179. if len(T.Args) != 0 { panic("something went wrong") }
  180. var yes_semi, err1 = Check(if_node.YesBranch, ctx)
  181. if err1 != nil { return SemiExpr{}, err1 }
  182. var yes_branch = SemiTypedBranch {
  183. IsDefault: false,
  184. Index: __Yes,
  185. Pattern: nil,
  186. Value: yes_semi,
  187. }
  188. var no_semi, err2 = Check(if_node.NoBranch, ctx)
  189. if err2 != nil { return SemiExpr{}, err2 }
  190. var no_branch = SemiTypedBranch {
  191. IsDefault: true,
  192. Index: BadIndex,
  193. Pattern: nil,
  194. Value: no_semi,
  195. }
  196. return SemiExpr {
  197. Info: info,
  198. Value: SemiTypedMatch {
  199. Argument: Expr(cond_typed),
  200. Branches: []SemiTypedBranch {
  201. yes_branch, no_branch,
  202. },
  203. },
  204. }, nil
  205. }
  206. }
  207. return SemiExpr{}, &ExprError {
  208. Point: ctx.GetErrorPoint(if_node.Condition.Node),
  209. Concrete: E_NonBooleanCondition {
  210. Typed: true,
  211. Type: ctx.DescribeType(cond_typed.Type),
  212. },
  213. }
  214. }
  215. func AssignMatchTo(expected Type, match SemiTypedMatch, info ExprInfo, ctx ExprContext) (Expr, *ExprError) {
  216. var err = RequireExplicitType(expected, info)
  217. if err != nil { return Expr{}, err }
  218. var branches = make([]Branch, len(match.Branches))
  219. for i, branch_semi := range match.Branches {
  220. var typed, err = AssignTo(expected, branch_semi.Value, ctx)
  221. if err != nil { return Expr{}, err }
  222. branches[i] = Branch {
  223. IsDefault: branch_semi.IsDefault,
  224. Index: branch_semi.Index,
  225. Pattern: branch_semi.Pattern,
  226. Value: typed,
  227. }
  228. }
  229. return Expr {
  230. Type: expected,
  231. Value: Match {
  232. Argument: match.Argument,
  233. Branches: branches,
  234. },
  235. Info: info,
  236. }, nil
  237. }
  238. func ExtractUnion(t Type, ctx ExprContext) (Union, []Type, bool) {
  239. switch T := t.(type) {
  240. case NamedType:
  241. var g = ctx.ModuleInfo.Types[T.Name]
  242. switch gv := g.Value.(type) {
  243. case Union:
  244. return gv, T.Args, true
  245. }
  246. }
  247. return Union{}, nil, false
  248. }
  249. func ExtractUnionTuple(t Type, ctx ExprContext) ([]Union, [][]Type, bool) {
  250. switch T := t.(type) {
  251. case NamedType:
  252. var g = ctx.ModuleInfo.Types[T.Name]
  253. switch gv := g.Value.(type) {
  254. case Boxed:
  255. var inner = FillTypeArgs(gv.InnerType, T.Args)
  256. switch inner_type := inner.(type) {
  257. case AnonymousType:
  258. switch tuple := inner_type.Repr.(type) {
  259. case Tuple:
  260. var union_types = make([]Union, len(tuple.Elements))
  261. var union_args = make([][]Type, len(tuple.Elements))
  262. for i, el := range tuple.Elements {
  263. switch el_t := el.(type) {
  264. case NamedType:
  265. var el_g = ctx.ModuleInfo.Types[el_t.Name]
  266. switch el_gv := el_g.Value.(type) {
  267. case Union:
  268. union_types[i] = el_gv
  269. union_args[i] = el_t.Args
  270. continue
  271. }
  272. }
  273. return nil, nil, false
  274. }
  275. return union_types, union_args, true
  276. }
  277. }
  278. }
  279. }
  280. return nil, nil, false
  281. }
  282. func DesugarElseIf(raw node.If) node.If {
  283. var no_branch = raw.NoBranch
  284. var elifs = raw.ElIfs
  285. for i, _ := range elifs {
  286. var elif = elifs[len(elifs)-1-i]
  287. var t = node.If {
  288. Node: elif.Node,
  289. Condition: elif.Condition,
  290. YesBranch: elif.YesBranch,
  291. NoBranch: no_branch,
  292. ElIfs: nil,
  293. }
  294. no_branch = node.Expr {
  295. Node: t.Node,
  296. Call: node.Call {
  297. Node: t.Node,
  298. Func: node.VariousTerm {
  299. Node: t.Node,
  300. Term: t,
  301. },
  302. Arg: nil,
  303. },
  304. Pipeline: nil,
  305. }
  306. }
  307. return node.If {
  308. Node: raw.Node,
  309. Condition: raw.Condition,
  310. YesBranch: raw.YesBranch,
  311. NoBranch: no_branch,
  312. ElIfs: nil,
  313. }
  314. }