lambda.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. package checker
  2. import (
  3. "kumachan/transformer/node"
  4. )
  5. func (impl UntypedLambda) SemiExprVal() {}
  6. type UntypedLambda struct {
  7. Input node.VariousPattern
  8. Output node.Expr
  9. }
  10. func (impl Lambda) ExprVal() {}
  11. type Lambda struct {
  12. Input Pattern
  13. Output Expr
  14. }
  15. func CheckLambda(lambda node.Lambda, ctx ExprContext) (SemiExpr, *ExprError) {
  16. var info = ctx.GetExprInfo(lambda.Node)
  17. return SemiExpr {
  18. Value: UntypedLambda {
  19. Input: lambda.Input,
  20. Output: node.Expr {
  21. Node: lambda.Node,
  22. Call: lambda.Output,
  23. Pipeline: nil,
  24. },
  25. },
  26. Info: info,
  27. }, nil
  28. }
  29. func AssignLambdaTo(expected Type, lambda UntypedLambda, info ExprInfo, ctx ExprContext) (Expr, *ExprError) {
  30. var err = RequireExplicitType(expected, info)
  31. if err != nil { return Expr{}, err }
  32. switch E := expected.(type) {
  33. case AnonymousType:
  34. switch func_repr := E.Repr.(type) {
  35. case Func:
  36. var input_t = func_repr.Input
  37. var output_t = func_repr.Output
  38. var input_param, is_param = input_t.(ParameterType)
  39. if ctx.InferTypeArgs {
  40. if is_param && input_param.BeingInferred {
  41. var inferred, exists = ctx.Inferred[input_param.Index]
  42. if exists {
  43. input_t = inferred
  44. } else {
  45. return Expr{}, &ExprError {
  46. Point: info.ErrorPoint,
  47. Concrete: E_ExplicitTypeRequired{},
  48. }
  49. }
  50. }
  51. }
  52. //
  53. var pattern, err1 = PatternFrom(lambda.Input, input_t, ctx)
  54. if err1 != nil { return Expr{}, err1 }
  55. //
  56. var inner_ctx = ctx.WithShadowingPatternMatching(pattern)
  57. var output_semi, err2 = Check(lambda.Output, inner_ctx)
  58. if err2 != nil { return Expr{}, err2 }
  59. //
  60. var output_typed, err3 = AssignTo(output_t, output_semi, inner_ctx)
  61. if err3 != nil { return Expr{}, err3 }
  62. return Expr {
  63. Type: expected,
  64. Info: info,
  65. Value: Lambda {
  66. Input: pattern,
  67. Output: output_typed,
  68. },
  69. }, nil
  70. }
  71. }
  72. return Expr{}, &ExprError {
  73. Point: info.ErrorPoint,
  74. Concrete: E_LambdaAssignedToNonFuncType {
  75. NonFuncType: ctx.DescribeType(expected),
  76. },
  77. }
  78. }
  79. func CallUntypedLambda (
  80. input SemiExpr,
  81. lambda UntypedLambda,
  82. lambda_info ExprInfo,
  83. call_info ExprInfo,
  84. ctx ExprContext,
  85. ) (SemiExpr, *ExprError) {
  86. var input_typed, input_is_typed = input.Value.(TypedExpr)
  87. if !input_is_typed {
  88. return SemiExpr{}, &ExprError {
  89. Point: lambda_info.ErrorPoint,
  90. Concrete: E_ExplicitTypeRequired {},
  91. }
  92. }
  93. var pattern, err1 = PatternFrom(lambda.Input, input_typed.Type, ctx)
  94. if err1 != nil { return SemiExpr{}, err1 }
  95. var inner_ctx = ctx.WithShadowingPatternMatching(pattern)
  96. var output, err2 = Check(lambda.Output, inner_ctx)
  97. if err2 != nil { return SemiExpr{}, err2 }
  98. var output_typed, output_is_typed = output.Value.(TypedExpr)
  99. if !output_is_typed {
  100. return SemiExpr{}, &ExprError {
  101. Point: lambda_info.ErrorPoint,
  102. Concrete: E_ExplicitTypeRequired {},
  103. }
  104. }
  105. var lambda_typed = Expr {
  106. Type: AnonymousType { Func {
  107. Input: input_typed.Type,
  108. Output: output_typed.Type,
  109. } },
  110. Value: Lambda {
  111. Input: pattern,
  112. Output: Expr(output_typed),
  113. },
  114. Info: lambda_info,
  115. }
  116. return LiftTyped(Expr{
  117. Type: output_typed.Type,
  118. Value: Call {
  119. Function: lambda_typed,
  120. Argument: Expr(input_typed),
  121. },
  122. Info: call_info, // this is a little ambiguous
  123. }), nil
  124. }