block.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. package checker
  2. import "kumachan/transformer/node"
  3. func (impl SemiTypedBlock) SemiExprVal() {}
  4. type SemiTypedBlock struct {
  5. Bindings [] Binding
  6. Returned SemiExpr
  7. }
  8. func (impl Block) ExprVal() {}
  9. type Block struct {
  10. Bindings [] Binding
  11. Returned Expr
  12. }
  13. type Binding struct {
  14. Pattern Pattern
  15. Value Expr
  16. Recursive bool
  17. }
  18. func CheckBlock(block node.Block, ctx ExprContext) (SemiExpr, *ExprError) {
  19. var info = ctx.GetExprInfo(block.Node)
  20. var type_ctx = ctx.GetTypeContext()
  21. var current_ctx = ctx
  22. var bindings = make([]Binding, len(block.Bindings))
  23. for i, b := range block.Bindings {
  24. var t Type
  25. switch type_node := b.Type.(type) {
  26. case node.VariousType:
  27. var some_t, err = TypeFrom(type_node.Type, type_ctx)
  28. if err != nil { return SemiExpr{}, &ExprError {
  29. Point: err.Point,
  30. Concrete: E_TypeErrorInExpr { err },
  31. }}
  32. t = some_t
  33. default:
  34. t = nil
  35. }
  36. if b.Recursive {
  37. if t == nil {
  38. return SemiExpr{}, &ExprError {
  39. Point: ctx.GetErrorPoint(b.Value.Node),
  40. Concrete: E_ExplicitTypeRequired {},
  41. }
  42. }
  43. var pattern, err1 = PatternFrom(b.Pattern, t, current_ctx)
  44. if err1 != nil { return SemiExpr{}, err1 }
  45. var rec_ctx, err2 = current_ctx.WithPatternMatching(pattern)
  46. if err2 != nil { return SemiExpr{}, err2 }
  47. var semi, err3 = Check(b.Value, rec_ctx)
  48. if err3 != nil { return SemiExpr{}, err3 }
  49. switch semi.Value.(type) {
  50. case UntypedLambda:
  51. var typed, err = AssignTo(t, semi, rec_ctx)
  52. if err != nil { return SemiExpr{}, err }
  53. bindings[i] = Binding {
  54. Pattern: pattern,
  55. Value: typed,
  56. Recursive: true,
  57. }
  58. current_ctx = rec_ctx
  59. default:
  60. return SemiExpr{}, &ExprError {
  61. Point: semi.Info.ErrorPoint,
  62. Concrete: E_RecursiveMarkUsedOnNonLambda {},
  63. }
  64. }
  65. } else {
  66. var semi, err1 = Check(b.Value, current_ctx)
  67. if err1 != nil { return SemiExpr{}, err1 }
  68. var typed, err2 = AssignTo(t, semi, current_ctx)
  69. if err2 != nil { return SemiExpr{}, err2 }
  70. var non_nil_t = typed.Type
  71. var pattern, err3 = PatternFrom(b.Pattern, non_nil_t, current_ctx)
  72. if err3 != nil { return SemiExpr{}, err3 }
  73. var next_ctx, err4 = current_ctx.WithPatternMatching(pattern)
  74. if err4 != nil { return SemiExpr{}, err4 }
  75. bindings[i] = Binding {
  76. Pattern: pattern,
  77. Value: typed,
  78. }
  79. current_ctx = next_ctx
  80. }
  81. }
  82. var ret, err = Check(block.Return, current_ctx)
  83. if err != nil { return SemiExpr{}, err }
  84. var ret_typed, is_typed = ret.Value.(TypedExpr)
  85. if is_typed {
  86. return LiftTyped(Expr {
  87. Type: ret_typed.Type,
  88. Value: Block {
  89. Bindings: bindings,
  90. Returned: Expr(ret_typed),
  91. },
  92. Info: info,
  93. }), nil
  94. } else {
  95. return SemiExpr {
  96. Value: SemiTypedBlock {
  97. Bindings: bindings,
  98. Returned: ret,
  99. },
  100. Info: info,
  101. }, nil
  102. }
  103. }
  104. func AssignBlockTo(expected Type, block SemiTypedBlock, info ExprInfo, ctx ExprContext) (Expr, *ExprError) {
  105. var bindings = block.Bindings
  106. var ret_semi = block.Returned
  107. var ret_typed, err = AssignTo(expected, ret_semi, ctx)
  108. if err != nil { return Expr{}, err }
  109. return Expr {
  110. Type: expected,
  111. Info: info,
  112. Value: Block {
  113. Bindings: bindings,
  114. Returned: ret_typed,
  115. },
  116. }, nil
  117. }