123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390 |
- package checker
- func GenericFunctionCall (
- f *GenericFunction,
- name string,
- index uint,
- type_args [] Type,
- arg SemiExpr,
- f_info ExprInfo,
- call_info ExprInfo,
- ctx ExprContext,
- unbox_count *uint, // mutate it instead of additional return value
- ) (Expr, *ExprError) {
- var type_arity = len(f.TypeParams)
- ctx = ctx.WithUnboxCounted(unbox_count)
- if len(type_args) == type_arity {
- var f_raw_type = AnonymousType { f.DeclaredType }
- var f_type = FillTypeArgs(f_raw_type, type_args)
- var f_type_repr = f_type.(AnonymousType).Repr.(Func)
- var input_type = f_type_repr.Input
- var output_type = f_type_repr.Output
- var arg_typed, err = AssignTo(input_type, arg, ctx)
- if err != nil { return Expr{}, err }
- return Expr {
- Type: output_type,
- Value: Call {
- Function: Expr {
- Type: f_type,
- Value: RefFunction {
- Name: name,
- Index: index,
- },
- Info: f_info,
- },
- Argument: arg_typed,
- },
- Info: call_info,
- }, nil
- } else if len(type_args) == 0 {
- var inf_ctx = ctx.WithTypeArgsInferringEnabled(f.TypeParams)
- var raw_input_type = f.DeclaredType.Input
- var raw_output_type = f.DeclaredType.Output
- var marked_input_type = MarkParamsAsBeingInferred(raw_input_type)
- var arg_typed, err = AssignTo(marked_input_type, arg, inf_ctx)
- if err != nil { return Expr{}, err }
- if len(inf_ctx.Inferred) != type_arity {
- return Expr{}, &ExprError {
- Point: f_info.ErrorPoint,
- Concrete: E_ExplicitTypeParamsRequired {},
- }
- }
- var inferred_args = make([]Type, type_arity)
- for i, t := range inf_ctx.Inferred {
- inferred_args[i] = t
- }
- var input_type = FillTypeArgs(raw_input_type, inferred_args)
- if !(AreTypesEqualInSameCtx(input_type, arg_typed.Type)) {
- panic("something went wrong")
- }
- var output_type = FillTypeArgs(raw_output_type, inferred_args)
- var f_type = AnonymousType { Func {
- Input: input_type,
- Output: output_type,
- } }
- return Expr {
- Type: output_type,
- Value: Call {
- Function: Expr {
- Type: f_type,
- Value: RefFunction {
- Name: name,
- Index: index,
- },
- Info: f_info,
- },
- Argument: arg_typed,
- },
- Info: call_info,
- }, nil
- } else {
- return Expr{}, &ExprError {
- Point: f_info.ErrorPoint,
- Concrete: E_FunctionWrongTypeParamsQuantity {
- FuncName: name,
- Given: uint(len(type_args)),
- Required: uint(type_arity),
- },
- }
- }
- }
- func GenericFunctionAssignTo (
- expected Type,
- name string,
- index uint,
- f *GenericFunction,
- type_args []Type,
- info ExprInfo,
- ctx ExprContext,
- ) (Expr, *ExprError) {
- var type_arity = len(f.TypeParams)
- if len(type_args) == type_arity {
- var f_raw_type = AnonymousType { f.DeclaredType }
- var f_type = FillTypeArgs(f_raw_type, type_args)
- var f_expr = Expr {
- Type: f_type,
- Value: RefFunction {
- Name: name,
- Index: index,
- },
- Info: info,
- }
- return AssignTypedTo(expected, f_expr, ctx, true)
- } else if len(type_args) == 0 {
- if expected == nil {
- return Expr{}, &ExprError {
- Point: info.ErrorPoint,
- Concrete: E_ExplicitTypeRequired {},
- }
- }
- var f_raw_type = AnonymousType { f.DeclaredType }
- // Note: Unbox/Union related inferring is not required
- // since function types are anonymous types and invariant.
- // Just apply NaivelyInferTypeArgs() here.
- var inferred = make(map[uint]Type)
- NaivelyInferTypeArgs(f_raw_type, expected, inferred)
- if len(inferred) == type_arity {
- var args = make([]Type, type_arity)
- for i, t := range inferred {
- args[i] = t
- }
- var f_type = FillTypeArgs(f_raw_type, args)
- if !(AreTypesEqualInSameCtx(f_type, expected)) {
- panic("something went wrong")
- }
- return Expr {
- Type: f_type,
- Value: RefFunction {
- Name: name,
- Index: index,
- },
- Info: info,
- }, nil
- } else {
- return Expr{}, &ExprError {
- Point: info.ErrorPoint,
- Concrete: E_ExplicitTypeParamsRequired {},
- }
- }
- } else {
- return Expr{}, &ExprError {
- Point: info.ErrorPoint,
- Concrete: E_FunctionWrongTypeParamsQuantity {
- FuncName: name,
- Given: uint(len(type_args)),
- Required: uint(type_arity),
- },
- }
- }
- }
- func FillTypeArgs(t Type, given []Type) Type {
- switch T := t.(type) {
- case ParameterType:
- return given[T.Index]
- case NamedType:
- var filled = make([]Type, len(T.Args))
- for i, arg := range T.Args {
- filled[i] = FillTypeArgs(arg, given)
- }
- return NamedType {
- Name: T.Name,
- Args: filled,
- }
- case AnonymousType:
- switch r := T.Repr.(type) {
- case Unit:
- return AnonymousType { Unit {} }
- case Tuple:
- var filled = make([]Type, len(r.Elements))
- for i, element := range r.Elements {
- filled[i] = FillTypeArgs(element, given)
- }
- return AnonymousType {
- Repr: Tuple {
- Elements: filled,
- },
- }
- case Bundle:
- var filled = make(map[string]Field, len(r.Fields))
- for name, field := range r.Fields {
- filled[name] = Field {
- Type: FillTypeArgs(field.Type, given),
- Index: field.Index,
- }
- }
- return AnonymousType {
- Repr: Bundle {
- Fields: filled,
- },
- }
- case Func:
- return AnonymousType {
- Repr:Func {
- Input: FillTypeArgs(r.Input, given),
- Output: FillTypeArgs(r.Output, given),
- },
- }
- default:
- panic("impossible branch")
- }
- default:
- panic("impossible branch")
- }
- }
- func NaivelyInferTypeArgs(template Type, given Type, inferred map[uint]Type) {
- switch T := template.(type) {
- case ParameterType:
- var existing, exists = inferred[T.Index]
- if !exists || AreTypesEqualInSameCtx(existing, given) {
- inferred[T.Index] = given
- }
- case NamedType:
- switch G := given.(type) {
- case NamedType:
- var L1 = len(T.Args)
- var L2 = len(G.Args)
- if L1 != L2 { panic("type registration went wrong") }
- var L = L1
- for i := 0; i < L; i += 1 {
- NaivelyInferTypeArgs(T.Args[i], G.Args[i], inferred)
- }
- }
- case AnonymousType:
- switch G := given.(type) {
- case AnonymousType:
- switch Tr := T.Repr.(type) {
- case Tuple:
- switch Gr := G.Repr.(type) {
- case Tuple:
- var L1 = len(Tr.Elements)
- var L2 = len(Gr.Elements)
- if L1 == L2 {
- var L = L1
- for i := 0; i < L; i += 1 {
- NaivelyInferTypeArgs(Tr.Elements[i], Gr.Elements[i], inferred)
- }
- }
- }
- case Bundle:
- switch Gr := G.Repr.(type) {
- case Bundle:
- for name, Tf := range Tr.Fields {
- var Gf, exists = Gr.Fields[name]
- if exists {
- NaivelyInferTypeArgs(Tf.Type, Gf.Type, inferred)
- }
- }
- }
- case Func:
- switch Gr := G.Repr.(type) {
- case Func:
- NaivelyInferTypeArgs(Tr.Input, Gr.Input, inferred)
- NaivelyInferTypeArgs(Tr.Output, Gr.Output, inferred)
- }
- default:
- panic("impossible branch")
- }
- }
- default:
- panic("impossible branch")
- }
- }
- func MarkParamsAsBeingInferred(type_ Type) Type {
- switch t := type_.(type) {
- case ParameterType:
- return ParameterType {
- Index: t.Index,
- BeingInferred: true,
- }
- case NamedType:
- var marked_args = make([]Type, len(t.Args))
- for i, arg := range t.Args {
- marked_args[i] = MarkParamsAsBeingInferred(arg)
- }
- return NamedType {
- Name: t.Name,
- Args: marked_args,
- }
- case AnonymousType:
- switch r := t.Repr.(type) {
- case Unit:
- return AnonymousType { Unit{} }
- case Tuple:
- var marked_elements = make([]Type, len(r.Elements))
- for i, el := range r.Elements {
- marked_elements[i] = MarkParamsAsBeingInferred(el)
- }
- return AnonymousType { Tuple { marked_elements } }
- case Bundle:
- var marked_fields = make(map[string]Field)
- for name, f := range r.Fields {
- marked_fields[name] = Field {
- Type: MarkParamsAsBeingInferred(f.Type),
- Index: f.Index,
- }
- }
- return AnonymousType { Bundle { marked_fields } }
- case Func:
- var marked_input = MarkParamsAsBeingInferred(r.Input)
- var marked_output = MarkParamsAsBeingInferred(r.Output)
- return AnonymousType { Func {
- Input: marked_input,
- Output: marked_output,
- } }
- default:
- panic("impossible branch")
- }
- default:
- panic("impossible branch")
- }
- }
- func FillMarkedParams(type_ Type, ctx ExprContext) Type {
- if !(ctx.InferTypeArgs) { panic("something went wrong") }
- switch T := type_.(type) {
- case ParameterType:
- if T.BeingInferred {
- var inferred, exists = ctx.Inferred[T.Index]
- if !exists { panic("something went wrong") }
- return inferred
- } else {
- return T
- }
- case NamedType:
- var filled = make([]Type, len(T.Args))
- for i, arg := range T.Args {
- filled[i] = FillMarkedParams(arg, ctx)
- }
- return NamedType {
- Name: T.Name,
- Args: filled,
- }
- case AnonymousType:
- switch r := T.Repr.(type) {
- case Unit:
- return AnonymousType { Unit {} }
- case Tuple:
- var filled = make([]Type, len(r.Elements))
- for i, element := range r.Elements {
- filled[i] = FillMarkedParams(element, ctx)
- }
- return AnonymousType {
- Repr: Tuple {
- Elements: filled,
- },
- }
- case Bundle:
- var filled = make(map[string]Field, len(r.Fields))
- for name, field := range r.Fields {
- filled[name] = Field {
- Type: FillMarkedParams(field.Type, ctx),
- Index: field.Index,
- }
- }
- return AnonymousType {
- Repr: Bundle {
- Fields: filled,
- },
- }
- case Func:
- return AnonymousType {
- Repr:Func {
- Input: FillMarkedParams(r.Input, ctx),
- Output: FillMarkedParams(r.Output, ctx),
- },
- }
- default:
- panic("impossible branch")
- }
- default:
- panic("impossible branch")
- }
- }
|