123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- package checker
- import (
- "kumachan/loader"
- "kumachan/transformer/node"
- )
- func (impl Sum) ExprVal() {}
- type Sum struct {
- Value Expr
- Index uint
- }
- func (impl UnitValue) ExprVal() {}
- type UnitValue struct {}
- func (impl SemiTypedMatch) SemiExprVal() {}
- type SemiTypedMatch struct {
- Argument Expr
- Branches [] SemiTypedBranch
- }
- type SemiTypedBranch struct {
- IsDefault bool
- Index uint
- Pattern MaybePattern
- Value SemiExpr
- }
- func (impl Match) ExprVal() {}
- type Match struct {
- Argument Expr
- Branches [] Branch
- }
- type Branch struct {
- IsDefault bool
- Index uint
- Pattern MaybePattern
- Value Expr
- }
- func CheckSwitch(sw node.Switch, ctx ExprContext) (SemiExpr, *ExprError) {
- var info = ctx.GetExprInfo(sw.Node)
- var arg_semi, err = CheckTerm(sw.Argument, ctx)
- if err != nil { return SemiExpr{}, err }
- var arg_typed, ok = arg_semi.Value.(TypedExpr)
- if !ok { return SemiExpr{}, &ExprError {
- Point: ctx.GetErrorPoint(sw.Argument.Node),
- Concrete: E_ExplicitTypeRequired {},
- } }
- var arg_type = arg_typed.Type
- var union, union_args, is_union = ExtractUnion(arg_type, ctx)
- if !is_union { return SemiExpr{}, &ExprError {
- Point: arg_typed.Info.ErrorPoint,
- Concrete: E_InvalidMatchArgType {
- ArgType: ctx.DescribeType(arg_typed.Type),
- },
- } }
- var checked = make(map[loader.Symbol] bool)
- var has_default = false
- var branches = make([]SemiTypedBranch, len(sw.Branches))
- for i, branch := range sw.Branches {
- switch t := branch.Type.(type) {
- case node.Ref:
- if len(t.TypeArgs) > 0 {
- return SemiExpr{}, &ExprError {
- Point: ctx.GetErrorPoint(t.Node),
- Concrete: E_TypeParametersUnnecessary {},
- }
- }
- var maybe_type_sym = ctx.ModuleInfo.Module.SymbolFromRef(t)
- var type_sym, ok = maybe_type_sym.(loader.Symbol)
- if !ok { return SemiExpr{}, &ExprError {
- Point: ctx.GetErrorPoint(t.Module.Node),
- Concrete: E_TypeErrorInExpr { &TypeError {
- Point: ctx.GetErrorPoint(t.Module.Node),
- Concrete: E_ModuleOfTypeRefNotFound {
- Name: loader.Id2String(t.Module),
- },
- } },
- }}
- var g, exists = ctx.ModuleInfo.Types[type_sym]
- if !exists { return SemiExpr{}, &ExprError {
- Point: ctx.GetErrorPoint(t.Node),
- Concrete: E_TypeErrorInExpr { &TypeError {
- Point: ctx.GetErrorPoint(t.Node),
- Concrete: E_TypeNotFound {
- Name: type_sym,
- },
- } },
- } }
- var index, is_subtype = GetSubtypeIndex(union, type_sym)
- if !is_subtype { return SemiExpr{}, &ExprError{
- Point: ctx.GetErrorPoint(t.Node),
- Concrete: E_NotBranchType {
- Union: ctx.DescribeType(arg_type),
- TypeName: type_sym.String(),
- },
- } }
- if len(g.Params) != len(union_args) {
- panic("something went wrong")
- }
- var subtype = NamedType {
- Name: type_sym,
- Args: union_args,
- }
- var maybe_pattern MaybePattern
- var branch_ctx ExprContext
- switch pattern_node := branch.Pattern.(type) {
- case node.VariousPattern:
- var pattern, err = PatternFrom(pattern_node, subtype, ctx)
- if err != nil { return SemiExpr{}, err }
- maybe_pattern = pattern
- branch_ctx = ctx.WithShadowingPatternMatching(pattern)
- default:
- maybe_pattern = nil
- branch_ctx = ctx
- }
- var semi, err = Check(
- branch.Expr, branch_ctx,
- )
- if err != nil { return SemiExpr{}, err }
- branches[i] = SemiTypedBranch {
- IsDefault: false,
- Index: index,
- Pattern: maybe_pattern,
- Value: semi,
- }
- checked[type_sym] = true
- default:
- if has_default {
- return SemiExpr{}, &ExprError {
- Point: ctx.GetErrorPoint(branch.Node),
- Concrete: E_DuplicateDefaultBranch {},
- }
- }
- switch branch.Pattern.(type) {
- case node.VariousPattern:
- panic("something went wrong")
- }
- var semi, err = Check(branch.Expr, ctx)
- if err != nil { return SemiExpr{}, nil }
- branches[i] = SemiTypedBranch {
- IsDefault: true,
- Index: BadIndex,
- Pattern: Pattern {},
- Value: semi,
- }
- has_default = true
- }
- }
- if !has_default && len(checked) != len(union.SubTypes) {
- var missing = make([]string, 0)
- for _, subtype := range union.SubTypes {
- if !checked[subtype] {
- missing = append(missing, subtype.String())
- }
- }
- return SemiExpr{}, &ExprError {
- Point: ctx.GetErrorPoint(sw.Node),
- Concrete: E_IncompleteMatch { missing },
- }
- } else {
- return SemiExpr {
- Value: SemiTypedMatch {
- Argument: Expr(arg_typed),
- Branches: branches,
- },
- Info: info,
- }, nil
- }
- }
- func CheckIf(raw node.If, ctx ExprContext) (SemiExpr, *ExprError) {
- var if_node = DesugarElseIf(raw)
- var info = ctx.GetExprInfo(if_node.Node)
- var cond_semi, err = CheckTerm(if_node.Condition, ctx)
- if err != nil { return SemiExpr{}, err }
- var cond_typed, ok = cond_semi.Value.(TypedExpr)
- if !ok { return SemiExpr{}, &ExprError{
- Point: ctx.GetErrorPoint(if_node.Condition.Node),
- Concrete: E_NonBooleanCondition { Typed:false },
- } }
- switch T := cond_typed.Type.(type) {
- case NamedType:
- if T.Name == __Bool {
- if len(T.Args) != 0 { panic("something went wrong") }
- var yes_semi, err1 = Check(if_node.YesBranch, ctx)
- if err1 != nil { return SemiExpr{}, err1 }
- var yes_branch = SemiTypedBranch {
- IsDefault: false,
- Index: __Yes,
- Pattern: nil,
- Value: yes_semi,
- }
- var no_semi, err2 = Check(if_node.NoBranch, ctx)
- if err2 != nil { return SemiExpr{}, err2 }
- var no_branch = SemiTypedBranch {
- IsDefault: true,
- Index: BadIndex,
- Pattern: nil,
- Value: no_semi,
- }
- return SemiExpr {
- Info: info,
- Value: SemiTypedMatch {
- Argument: Expr(cond_typed),
- Branches: []SemiTypedBranch {
- yes_branch, no_branch,
- },
- },
- }, nil
- }
- }
- return SemiExpr{}, &ExprError {
- Point: ctx.GetErrorPoint(if_node.Condition.Node),
- Concrete: E_NonBooleanCondition {
- Typed: true,
- Type: ctx.DescribeType(cond_typed.Type),
- },
- }
- }
- func AssignMatchTo(expected Type, match SemiTypedMatch, info ExprInfo, ctx ExprContext) (Expr, *ExprError) {
- var err = RequireExplicitType(expected, info)
- if err != nil { return Expr{}, err }
- var branches = make([]Branch, len(match.Branches))
- for i, branch_semi := range match.Branches {
- var typed, err = AssignTo(expected, branch_semi.Value, ctx)
- if err != nil { return Expr{}, err }
- branches[i] = Branch {
- IsDefault: branch_semi.IsDefault,
- Index: branch_semi.Index,
- Pattern: branch_semi.Pattern,
- Value: typed,
- }
- }
- return Expr {
- Type: expected,
- Value: Match {
- Argument: match.Argument,
- Branches: branches,
- },
- Info: info,
- }, nil
- }
- func ExtractUnion(t Type, ctx ExprContext) (Union, []Type, bool) {
- switch T := t.(type) {
- case NamedType:
- var g = ctx.ModuleInfo.Types[T.Name]
- switch gv := g.Value.(type) {
- case Union:
- return gv, T.Args, true
- }
- }
- return Union{}, nil, false
- }
- func ExtractUnionTuple(t Type, ctx ExprContext) ([]Union, [][]Type, bool) {
- switch T := t.(type) {
- case NamedType:
- var g = ctx.ModuleInfo.Types[T.Name]
- switch gv := g.Value.(type) {
- case Boxed:
- var inner = FillTypeArgs(gv.InnerType, T.Args)
- switch inner_type := inner.(type) {
- case AnonymousType:
- switch tuple := inner_type.Repr.(type) {
- case Tuple:
- var union_types = make([]Union, len(tuple.Elements))
- var union_args = make([][]Type, len(tuple.Elements))
- for i, el := range tuple.Elements {
- switch el_t := el.(type) {
- case NamedType:
- var el_g = ctx.ModuleInfo.Types[el_t.Name]
- switch el_gv := el_g.Value.(type) {
- case Union:
- union_types[i] = el_gv
- union_args[i] = el_t.Args
- continue
- }
- }
- return nil, nil, false
- }
- return union_types, union_args, true
- }
- }
- }
- }
- return nil, nil, false
- }
- func DesugarElseIf(raw node.If) node.If {
- var no_branch = raw.NoBranch
- var elifs = raw.ElIfs
- for i, _ := range elifs {
- var elif = elifs[len(elifs)-1-i]
- var t = node.If {
- Node: elif.Node,
- Condition: elif.Condition,
- YesBranch: elif.YesBranch,
- NoBranch: no_branch,
- ElIfs: nil,
- }
- no_branch = node.Expr {
- Node: t.Node,
- Call: node.Call {
- Node: t.Node,
- Func: node.VariousTerm {
- Node: t.Node,
- Term: t,
- },
- Arg: nil,
- },
- Pipeline: nil,
- }
- }
- return node.If {
- Node: raw.Node,
- Condition: raw.Condition,
- YesBranch: raw.YesBranch,
- NoBranch: no_branch,
- ElIfs: nil,
- }
- }
|