123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- package checker
- import (
- "kumachan/interpreter/lang/ast"
- "kumachan/interpreter/lang/common/name"
- "kumachan/interpreter/lang/common/source"
- "kumachan/interpreter/compiler/checker/typsys"
- "kumachan/interpreter/compiler/checker/checked"
- )
- func checkBlank(B ast.TermBlank) ExprChecker {
- return makeExprChecker(B.Location, func(cc *checkContext) checkResult {
- return cc.error(E_BlankTerm {})
- })
- }
- func checkCast(arg_node ast.Expr, target ast.VariousType, loc source.Location) ExprChecker {
- return makeExprChecker(loc, func(cc *checkContext) checkResult {
- var type_ctx = cc.typeConsContext()
- var target_t, err1 = newType(target, type_ctx)
- if err1 != nil { return cc.propagate(err1) }
- var arg, err2 = cc.checkChildExpr(target_t, arg_node)
- if err2 != nil { return cc.propagate(err2) }
- return cc.assign(target_t, checked.Wrapper { Inner: arg })
- })
- }
- func checkInterior(arg *checked.Expr, mod_name ast.ModuleName, item_name ast.Identifier, loc source.Location) ExprChecker {
- return makeExprChecker(loc, func(cc *checkContext) checkResult {
- var mod_name_not_empty = mod_name.NotEmpty
- { var i_def, i_args, op, base, is_interface = cc.unboxInteriorReferableInterfaceDef(arg)
- if !(is_interface) && mod_name_not_empty {
- return cc.propagate(source.MakeError(arg.Info.Location,
- E_DynamicCastFromNonInterface {
- Type: cc.describeType(arg.Type),
- }))
- }
- if is_interface {
- var c_name, err = NameFrom(
- mod_name, item_name, cc.exprContext.ModuleInfo,
- )
- if err != nil {
- return cc.propagate(err)
- }
- var ctx = cc.typeConsContext()
- var c_def_, c_def_desc, exists = ctx.ResolveTypeDefName(c_name)
- if !(exists) {
- return cc.propagate(source.MakeError(item_name.Location,
- E_TypeNotFound { Which: c_def_desc() }))
- }
- var c_def = c_def_.TypeDef
- var _, c_is_interface = c_def.Content.(*typsys.Interface)
- if c_is_interface {
- return cc.error(E_DynamicCastToInterface {})
- }
- var p = ImplPair {
- ConcreteType: c_def,
- InterfaceType: i_def,
- }
- var table, ok = cc.exprContext.DispatchMapping[p]
- if !(ok) {
- var c_type_name = name.TypeName { Name: c_name }
- var i_type_name = i_def.Name
- return cc.error(
- E_NotImplementation {
- Type: c_type_name.String(),
- Interface: i_type_name.String(),
- })
- }
- var c_type = &typsys.NestedType { Content: typsys.Ref {
- Def: c_def,
- Args: i_args,
- } }
- var ref_type = cc.getType(coreCaseRef(
- base,
- c_type,
- ))
- return cc.assign(
- ref_type,
- checked.InteriorRef {
- Base: arg,
- Table: table,
- Kind: checked.RK_InterfaceCase,
- Operand: op,
- })
- } }
- { var key = ast.Id2String(item_name)
- { var record, op, base, is_record = cc.unboxInteriorReferableRecord(arg)
- if is_record {
- var index, exists = record.FieldIndexMap[key]
- if !(exists) { goto key_not_found }
- var field_t = record.Fields[index].Type
- var ref_t = cc.getType(coreProjRef(base, field_t))
- return cc.assign(
- ref_t,
- checked.InteriorRef {
- Base: arg,
- Index: index,
- Kind: checked.RK_Proj,
- Operand: op,
- })
- } }
- { var enum, ea, op, base, is_enum = cc.unboxInteriorReferableEnum(arg)
- if is_enum {
- var ci uint
- var cd *typsys.TypeDef
- var found = false
- for i, case_def := range enum.CaseTypes {
- if case_def.Name.ItemName == key {
- ci = uint(i)
- cd = case_def
- found = true
- }
- }
- if !(found) { goto key_not_found }
- var case_t = &typsys.NestedType { Content:
- typsys.Ref {
- Def: cd,
- Args: ea,
- } }
- var ref_t = cc.getType(coreCaseRef(base, case_t))
- return cc.assign(
- ref_t,
- checked.InteriorRef {
- Base: arg,
- Index: ci,
- Kind: checked.RK_Case,
- Operand: op,
- })
- } }
- key_not_found:
- return cc.propagate(source.MakeError(item_name.Location,
- E_NoSuchFieldOrCase {
- FieldName: key,
- TypeName: cc.describeTypeOf(arg),
- })) }
- })
- }
- func checkList(L ast.Array) ExprChecker {
- return makeExprChecker(L.Location, func(cc *checkContext) checkResult {
- if len(L.Items) == 0 {
- return cc.assign(
- cc.getType(coreList(typsys.BottomType {})),
- checked.List {
- Items: [] *checked.Expr {},
- Info: checked.ListInfo {},
- })
- }
- var item_t, ok = cc.getExpectedListItemType(cc.expected)
- if ok {
- var items = make([] *checked.Expr, len(L.Items))
- for i, item_node := range L.Items {
- var item, err = cc.checkChildExpr(item_t, item_node)
- if err != nil { return cc.throw(err) }
- items[i] = item
- }
- var item_t, err = cc.requireCertainOrInferredType(item_t)
- if err != nil { return cc.throw(err) }
- var list_t = cc.getType(coreList(item_t))
- return cc.assign(
- list_t,
- checked.List {
- Items: items,
- Info: getListInfo(item_t),
- })
- } else {
- var item_t = typsys.Type(nil)
- var items = make([] *checked.Expr, len(L.Items))
- for i, item_node := range L.Items {
- var item, err = cc.checkChildExpr(item_t, item_node)
- if err != nil { return cc.propagate(err) }
- if item_t == nil {
- item_t = item.Type
- }
- items[i] = item
- }
- if item_t == nil { panic("something went wrong") }
- var list_t = cc.getType(coreList(item_t))
- return cc.assign(
- list_t,
- checked.List {
- Items: items,
- Info: getListInfo(item_t),
- })
- }
- })
- }
- func checkPipelineLambda(P ast.PipelineLambda) ExprChecker {
- return checkQuickLambda(P.Node, quickPipelineLambda(P))
- }
- func quickPipelineLambda(P ast.PipelineLambda) quickLambda {
- return func(arg ast.Expr) ast.Expr {
- return ast.Expr {
- Node: P.Node,
- Term: ast.WrapExprIntoTerm(arg),
- Pipeline: P.Pipeline,
- }
- }
- }
- func checkConstructorLambda(C ast.ConstructorLambda) ExprChecker {
- return makeExprChecker(C.Location, func(cc *checkContext) checkResult {
- var type_ctx = cc.typeConsContext()
- var f, err = quickConstructorLambda(C, type_ctx)
- if err != nil { return cc.propagate(err) }
- return cc.forward(checkQuickLambda(C.Node, f))
- })
- }
- func quickConstructorLambda(C ast.ConstructorLambda, type_ctx TypeConsContext) (quickLambda, *source.Error) {
- var def, args, err = newRefNoCheckArgQuantity(C.Type, type_ctx)
- if err != nil { return nil, err }
- return func(arg ast.Expr) ast.Expr {
- return ast.Expr {
- Node: C.Node,
- Term: ast.VariousTerm {
- Node: C.Node,
- Term: ConstructorCallTerm {
- TypeDef: def,
- TypeArgs: args,
- Argument: arg,
- },
- },
- }
- }, nil
- }
|